home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / src / lpvmshmem.c < prev    next >
Text File  |  1997-07-22  |  66KB  |  2,785 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: lpvmshmem.c,v 1.28 1997/07/08 21:25:50 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34.  *    lpvmshmem.c
  35.  *
  36.  *    Libpvm core for MPP environment.
  37.  *
  38. $Log: lpvmshmem.c,v $
  39.  * Revision 1.28  1997/07/08  21:25:50  pvmsrc
  40.  * peer_send() now directs control TC messages via the daemon.
  41.  * node_mcast() is no-longer called until its pmsg buffer error is found,
  42.  * i.e. mcast messages are sent via the daemon, using a MCA instead of directly.
  43.  * pvmmcast() sets the context to the current default.
  44.  * msendrecv() now takes a context arg! It sets it as well (and the waitid).
  45.  * beatask() uses SYS contexts on handshakes.
  46.  *
  47.  * Revision 1.27  1997/07/03  17:41:50  pvmsrc
  48.  * Added new sleep_dammit() routine.
  49.  *     - usleep() on SUNMP, RS6KMP, AIX4MP.
  50.  *     - select() w/ timeout everywhere else.
  51.  *
  52.  * Revision 1.26  1997/07/02  20:34:58  pvmsrc
  53.  * Commented out usleep() call.
  54.  *     - not implemented on every arch...
  55.  *
  56.  * Revision 1.25  1997/07/02  14:33:45  pvmsrc
  57.  * beatask() connection attempt tries harder by kicking the daemon
  58.  *     out of select().
  59.  *
  60.  * Revision 1.24  1997/06/27  20:48:08  pvmsrc
  61.  * Missed AIX arches on write test.
  62.  *
  63.  * Revision 1.23  1997/06/25  22:09:10  pvmsrc
  64.  * Markus adds his frigging name to the author list of
  65.  *     every file he ever looked at...
  66.  *
  67.  * Revision 1.22  1997/06/16  13:42:44  pvmsrc
  68.  * Oops...  My mistake.  D-Oh.
  69.  *     - can't use mid as struct pmsg * damn damn damn.
  70.  *     - wouldn't have been a problem if stupid shmem code didn't
  71.  *         call mroute() down inside system...  :-/~
  72.  *
  73.  * Revision 1.21  1997/06/12  20:10:46  pvmsrc
  74.  * Made sure all communications for TC_* task control messages
  75.  *     use the SYSCTX_TC system context.
  76.  *     - some messages being sent in default context...  D-Oh...
  77.  *
  78.  * Revision 1.20  1997/06/02  13:50:02  pvmsrc
  79.  * Added missing #include host.h for waitc.h.
  80.  *
  81.  * Revision 1.19  1997/06/02  13:24:13  pvmsrc
  82.  * Added test to shmemuptod()
  83.  *     - so that it creates daemon socket if it doesn't already exist.
  84.  *
  85.  * Revision 1.18  1997/05/29  15:14:05  pvmsrc
  86.  * Removed static decls:
  87.  *     - pvmtrcsbf, pvmrouteopt now in lpvmglob.c / lpvm.h.
  88.  *     - pvmtrcmid doesn't exist.
  89.  * Fixed arg casting for SGI's:
  90.  *     - read_int() takes (int *), not (struct pidtidhdr *)...
  91.  *
  92.  * Revision 1.17  1997/05/27  15:05:30  pvmsrc
  93.  * Added SHMCONN handshake code into pvmbeatask():
  94.  *     via new call send_my_pid().
  95.  *     - this removes strange floating tid 0 processes...
  96.  *     - send_my_pid() calls new function shmemuptod() which is a
  97.  *         simplified one-way mxfer().
  98.  *     - shmem node tasks still do not read from pvmd via sockets.
  99.  * Text formatting (JAK).
  100.  *
  101.  * Revision 1.16  1997/05/21  16:01:50  pvmsrc
  102.  * Updated ifdefs to include AIX4MP arch type.
  103.  *
  104.  * Revision 1.15  1997/05/21  15:45:41  pvmsrc
  105.  * pvm_tc_taskexit handled correctly.
  106.  *     Reports error only when no peer entry exits.
  107.  *
  108.  * Revision 1.14  1997/05/19  15:00:56  pvmsrc
  109.  * Number of small fixes:
  110.  *     midtobuf, umbuf_new are prototyped correctly now.
  111.  *     msg contexts set/read correctly in peer_send & peer_recv.
  112.  *     pvmbeatask():
  113.  *         shmem key id allocated/located without bizzare attachment error.
  114.  *         waitc struct is now set using wait_init() before first use... ;)
  115.  *     pvmmcast():
  116.  *         mroute is called with a valid mid
  117.  *         TT direct routes are not checked until ttpcb is defined
  118.  *
  119.  * Revision 1.13  1997/04/30  21:26:07  pvmsrc
  120.  * SGI Compiler Warning Cleanup.
  121.  *
  122.  * Revision 1.12  1997/04/25  19:19:40  pvmsrc
  123.  * altered to allow integration into 3.4 messaging.
  124.  * Changes:
  125.  *     -    includes
  126.  *     -     added mhp struct def (same as pmsg)
  127.  *     -     updated pvmmidh, pvmmidsiz and m_umbs
  128.  *     -     added ttpcd lists
  129.  *     -     own copy of pvmmcast() (same as lpvm.c)
  130.  *     -     own copy of ttpcb_find() minus mpp_ttpcb_find routine XXX
  131.  *     -     own copy of post_routedelete() (from lpvmgen.c)
  132.  *
  133.  * Revision 1.11  1997/04/07  21:09:14  pvmsrc
  134.  * pvm_addmhf() - new paramter interface
  135.  *
  136.  * Revision 1.10  1997/04/01  21:28:18  pvmsrc
  137.  * Damn Damn Damn.
  138.  *     - pvm_recvinfo() returns a bufid, not an index.  Damn.
  139.  *
  140.  * Revision 1.9  1997/04/01  20:48:21  pvmsrc
  141.  * Fixed tracer mbox usage:
  142.  *     - pvm_getinfo() -> pvm_recvinfo(), new semantics handled (recvinfo
  143.  *         sets rbuf implicitly, a la pvm_recv, need to save rbuf).
  144.  *
  145.  * Revision 1.8  1997/03/27  19:55:31  pvmsrc
  146.  * Fixed up pvmbeatask() to go get tracer info if spawned from shell:
  147.  *     - env var info including trace mask, trace buffer size, trace opts.
  148.  *     - use PVMTRACERCLASS mbox entry to fill in values, if matches
  149.  *         on trctid, trcctx, and trctag.
  150.  *
  151.  * Revision 1.7  1997/03/06  21:50:21  pvmsrc
  152.  * Yanked out #includes for <netinet/in.h> and <netinet/tcp.h>.
  153.  *     - dups with lpvm.h #includes...
  154.  *
  155.  * Revision 1.6  1997/01/28  19:26:52  pvmsrc
  156.  * New Copyright Notice & Authors.
  157.  *
  158.  * Revision 1.5  1996/12/19  19:57:58  pvmsrc
  159.  * Eradicated remainder of old control message interface.
  160.  *     - replaced pvmmctl() routine with individual messages handlers:
  161.  *         * pvm_tc_shmat() (lpvmshmem.c only).
  162.  *         * pvm_tc_conreq().
  163.  *         * pvm_tc_conack().
  164.  *         * pvm_tc_taskexit().
  165.  *     - added appropriate calls to pvm_addmhf() in pvmbeatask().
  166.  *     - removed calls to pvmmctl() in mroute() (peer_recv() in
  167.  *         lpvmshmem.c), replaced with new mesg_input() call,
  168.  *         use new pmsg_setenc() routine to set message encoding.
  169.  *
  170.  * Revision 1.4  1996/12/18  22:27:50  pvmsrc
  171.  * Extracted duplicate versions of routines from lpvm/mimd/shmem.c,
  172.  *     inserted into shared lpvmgen.c:
  173.  *     - pvmbailout().
  174.  *     - pvmlogerror().
  175.  *     - vpvmlogprintf(), pvmlogprintf().  (hope these work on MPP & shmem)
  176.  *     - pvmlogperror().
  177.  *
  178.  * Revision 1.3  1996/10/25  13:57:31  pvmsrc
  179.  * Replaced old #includes for protocol headers:
  180.  *     - <pvmsdpro.h>, "ddpro.h", "tdpro.h"
  181.  * With #include of new combined header:
  182.  *     - <pvmproto.h>
  183.  *
  184.  * Revision 1.2  1996/10/24  22:44:35  pvmsrc
  185.  * Modified for New Tracing Facility:
  186.  *     - moved #include "global.h" below other #include's for typing.
  187.  *     - removed extra #include <pvm3.h> in lpvm.c...
  188.  *     - added #include of new "lpvm.h" to replace explicit externs.
  189.  *     - removed common control message handlers from lpvm.c:
  190.  *         * extracted to lpvmgen.c for general usage.
  191.  *         * pvm_tc_noop(), pvm_tc_settmask(), pvm_tc_siblings().
  192.  *         -> lpvmmimd.c & lpvmshmem.c still need remainder of pvmmctl()
  193.  *             replaced with control message handlers.
  194.  *     - arg typing hassles with int_compare() / qsort() exacerbated...
  195.  *     - modified pvmbeatask():
  196.  *         * handle new tracing info, unpack tracing and output collection
  197.  *             parameters into temp storage, and then check for local task
  198.  *             override before applying.
  199.  *         * read in new tracing env vars PVMTRCBUF & PVMTRCOPT.
  200.  *         * install new common message handlers.
  201.  *         * call new tev_init() routine to set up tracing stuff.
  202.  *         * use new Pvmtracer structures (pvmtrc & pvmctrc) to store info.
  203.  *     - removed pvm_getopt() & pvm_setopt() -> moved to common lpvmgen.c.
  204.  *     - removed old tev_begin(), tev_fin() & tev_do_trace() routines.
  205.  *     - updated trace event generation for pvm_getfds(), pvm_start_pvmd(),
  206.  *         pvm_precv(), pvm_psend().
  207.  *
  208.  * Revision 1.1  1996/09/23  23:44:20  pvmsrc
  209.  * Initial revision
  210.  *
  211.  * Revision 1.39  1995/11/10  21:37:46  manchek
  212.  * check for EINTR from semop in peer_wait
  213.  *
  214.  * Revision 1.38  1995/11/02  16:17:20  manchek
  215.  * free replies to control messages in mxfer
  216.  *
  217.  * Revision 1.37  1995/09/08  17:26:02  manchek
  218.  * aargh forgot semicolon
  219.  *
  220.  * Revision 1.36  1995/09/08  16:56:17  manchek
  221.  * experimental changes to pvm_psend to improve performance (postpone freebuf)
  222.  *
  223.  * Revision 1.35  1995/09/06  17:37:24  manchek
  224.  * aargh, forgot pvm_precv
  225.  *
  226.  * Revision 1.34  1995/09/06  17:31:41  manchek
  227.  * pvm_psend returns not implemented instead of bad param for string type
  228.  *
  229.  * Revision 1.33  1995/09/05  19:20:30  manchek
  230.  * changes from bigapple to make busywait work better
  231.  *
  232.  * Revision 1.32  1995/07/28  16:40:59  manchek
  233.  * wrap HASERRORVARS around errno declarations
  234.  *
  235.  * Revision 1.31  1995/07/28  15:35:19  manchek
  236.  * address of copy databuf wasn't set right in peer_send
  237.  *
  238.  * Revision 1.30  1995/07/28  15:10:37  manchek
  239.  * only send message header on first fragment
  240.  *
  241.  * Revision 1.29  1995/07/28  15:07:30  manchek
  242.  * peer_send wasn't generating message checksum
  243.  *
  244.  * Revision 1.28  1995/07/24  18:45:51  manchek
  245.  * message headers passed in inbox shmpkhdr instead of databuf
  246.  * requires changes to peer_recv, peer_send, msendrecv.
  247.  * use pvmnametag function to print message tags symbolically
  248.  *
  249.  * Revision 1.27  1995/07/19  16:37:51  manchek
  250.  * peer_send returns NotImpl if DataInPlace used
  251.  *
  252.  * Revision 1.26  1995/07/18  17:00:13  manchek
  253.  * added code to generate and check crc on each message (MCHECKSUM).
  254.  * get and put wait-id in message header
  255.  *
  256.  * Revision 1.25  1995/07/12  01:20:40  manchek
  257.  * initialize lots of globals, reset in pvmendtask.
  258.  * pvmendtask checks that globals are set before using them.
  259.  * catch_kill reinstalls old sighldr, doesn't call if it's SIG_IGN,
  260.  * sets pidtid state to ST_FINISH.
  261.  * peer_detach now frees the peer struct
  262.  *
  263.  * Revision 1.24  1995/07/11  18:58:30  manchek
  264.  * peer_wait returns int, -1 if error reading semaphore.
  265.  * mroute and dynbuf check peer_wait return for error
  266.  *
  267.  * Revision 1.23  1995/07/05  16:18:10  manchek
  268.  * exiting task sets pidtid entry state to ST_FINISH instead of ST_EXIT
  269.  *
  270.  * Revision 1.22  1995/07/05  15:36:40  manchek
  271.  * free messages before sending TASKEXIT in pvmendtask
  272.  *
  273.  * Revision 1.21  1995/07/03  20:51:15  manchek
  274.  * made convex poll-type code in peer_wait() the default case
  275.  *
  276.  * Revision 1.20  1995/07/03  20:18:26  manchek
  277.  * hellish cleanup of comments and formatting.
  278.  * removed POWER4 ifdefs.
  279.  * added deadlock detection where task owns all pages in shared
  280.  * segment and needs still another
  281.  *
  282.  * Revision 1.19  1995/06/30  16:24:45  manchek
  283.  * aargh
  284.  *
  285.  * Revision 1.18  1995/06/28  18:17:56  manchek
  286.  * moved check_for_exit from pvmumbuf.c
  287.  *
  288.  * Revision 1.17  1995/06/28  17:59:11  manchek
  289.  * typo
  290.  *
  291.  * Revision 1.16  1995/06/28  15:47:18  manchek
  292.  * added TC_SHMAT connect handshake
  293.  *
  294.  * Revision 1.15  1995/06/19  17:47:58  manchek
  295.  * was packing random string in TC_CONACK message in pvmmctl
  296.  *
  297.  * Revision 1.14  1995/06/02  17:21:34  manchek
  298.  * pvm_start_pvmd ignores INT, QUIT, TSTP signals
  299.  *
  300.  * Revision 1.13  1995/05/30  14:48:37  manchek
  301.  * in pvmendtask() must call peer_cleanup() before erasing our tid
  302.  *
  303.  * Revision 1.12  1995/05/24  19:07:37  manchek
  304.  * small fix in getdsock().
  305.  * changed HPPA shared memory name to HPPAMP
  306.  *
  307.  * Revision 1.11  1995/05/22  19:45:45  manchek
  308.  * added ifdefs for RS6KMP
  309.  *
  310.  * Revision 1.10  1995/05/22  19:09:02  manchek
  311.  * took out ifdefs around read_int().
  312.  * with new startup, can read pvmd sockaddr file only once
  313.  *
  314.  * Revision 1.9  1995/05/18  17:22:08  manchek
  315.  * need to export pvminbox and myshmbufid
  316.  *
  317.  * Revision 1.8  1995/05/17  16:21:17  manchek
  318.  * added support for CSPP shared memory.
  319.  * lots of bug fixes from SGI and Convex.
  320.  * added PVMTASKDEBUG envar.
  321.  * pvm_start_pvmd reads sockaddr from pvmd instead of sleeping on addr file.
  322.  * CSPP port (only) uses new TM_GETOPT message to get trace, output dest.
  323.  *
  324.  * Revision 1.7  1995/02/06  21:43:59  manchek
  325.  * pvmmctl now replies to TC_CONREQ message.
  326.  * better cleanup of message buffers in pvmendtask
  327.  *
  328.  * Revision 1.6  1995/02/01  21:24:47  manchek
  329.  * error 4 is now PvmOverflow
  330.  *
  331.  * Revision 1.5  1994/12/20  16:38:44  manchek
  332.  * added pvmshowtaskid variable
  333.  *
  334.  * Revision 1.4  1994/11/07  22:42:39  manchek
  335.  * general damage control and cleanup:
  336.  * initialize variables
  337.  * send null packets to wake up pvmd instead of reconnecting
  338.  * clean up on catching SIGTERM
  339.  *
  340.  * Revision 1.3  1994/06/30  21:35:40  manchek
  341.  * typo in peer_recv()
  342.  *
  343.  * Revision 1.2  1994/06/04  21:44:31  manchek
  344.  * updated header.
  345.  * changed TM_SET to TM_SETOPT
  346.  *
  347.  * Revision 1.1  1994/06/03  20:38:18  manchek
  348.  * Initial revision
  349.  *
  350.  */
  351.  
  352. #include <sys/param.h>
  353. #include <stdio.h>
  354. #include <rpc/types.h>
  355. #include <rpc/xdr.h>
  356. #include <sys/socket.h>
  357. #include <sys/stat.h>
  358. #include <fcntl.h>
  359. #ifdef    SYSVSTR
  360. #include <string.h>
  361. #else
  362. #include <strings.h>
  363. #endif
  364. #include <signal.h>
  365. #include <errno.h>
  366. #include <sys/ipc.h>
  367. #include <sys/shm.h>
  368. #include <sys/sem.h>
  369. #include <sys/mman.h>
  370. #include <unistd.h>
  371. #ifdef IMA_SYMM
  372. #include <parallel/parallel.h>
  373. #endif
  374. #ifdef IMA_KSR1
  375. #include <pthread.h>
  376. #endif
  377. #include <sys/time.h>
  378. #ifdef NEEDSSELECTH
  379. #include <sys/select.h>
  380. #endif
  381.  
  382. #include <pvm3.h>
  383. #include <pvmproto.h>
  384. #include "pvmalloc.h"
  385. #include "pvmdabuf.h"
  386. #include "pvmfrag.h"
  387. #include "pmsg.h"
  388. #include "listmac.h"
  389. #include "pvmshmem.h"
  390. #include "bfunc.h"
  391. #include "lpvm.h"
  392. #include "host.h"
  393. #include "waitc.h" /* needed by post_routedelete */
  394. #include <pvmtev.h>
  395. #include "tevmac.h"
  396. #include "global.h"
  397.  
  398. #ifndef max
  399. #define max(a,b)    ((a)>(b)?(a):(b))
  400. #endif
  401.  
  402. #ifndef min
  403. #define min(a,b)    ((a)<(b)?(a):(b))
  404. #endif
  405.  
  406. char *getenv();
  407. void hex_inadport __ProtoGlarp__ (( char *, struct sockaddr_in * ));
  408.  
  409. /* These prototypes stop compiler casting structs to ints... */
  410. struct pmsg *midtobuf(); /* Oops someone forgot this one KEV/GEF */
  411. struct pmsg *umbuf_new(); /* Here is another :) KEV/GEF */
  412.  
  413.  
  414. extern struct encvec *enctovec();
  415. char *pvmgetpvmd();
  416. char *pvmgethome();
  417. char *pvmdsockfile();
  418. char *pvmnametag();
  419.  
  420. #ifdef IMA_CSPP
  421. int current_node();
  422. #endif
  423.  
  424.  
  425. /***************
  426.  **  Globals  **
  427.  **           **
  428.  ***************/
  429.  
  430. #ifndef HASERRORVARS
  431. extern int errno;                    /* from libc */
  432. extern char *sys_errlist[];
  433. extern int sys_nerr;
  434. #endif
  435.  
  436. /* XXX this should be in a header file not copied */
  437. /* message heap element */
  438.  
  439. struct mhp {
  440.     int m_free;                 /* free list (next or 0) */
  441.     struct pmsg *m_umb;         /* message or null if on free list */
  442. };
  443.  
  444.  
  445. extern int bufpageused;                /* from pvmshmem.c */
  446. extern struct mhp *pvmmidh;            /* from lpvmpack.c */
  447. extern int pvmmidhsiz;                /* from lpvmpack.c */
  448.  
  449. int shmbufsiz = 0;                    /* shared-memory buffer size */
  450.  
  451. int pvmtidhmask = TIDHOST;            /* mask - host field of tids */
  452. int pvmtidlmask = TIDLOCAL;            /* mask - local field of tids */
  453.  
  454. int pgsz = 0;                        /* system page size */
  455. int pvmpgsz = 0;                    /* PVM virtual page size */
  456. char *outmsgbuf = 0;                /* my outgoing message buffer */
  457. int outbufsz = 0;                    /* # of frags in outgoing msg buf */
  458. int nbufsowned = 0;                    /* num shared frags held by us */
  459. struct pidtid *pidtids = 0;            /* pid -> tid table */
  460. char *infopage = 0;                    /* proto, NDF, pid-tid table */
  461. int maxpidtid = 0;                    /* size of pid-tid table */
  462. int myshmbufid = -1;                /* ID of shared-memory buffer */
  463. char *pvminbox = 0;                    /* incoming message buffer */
  464.  
  465. struct pmsg *m_umb;            /* message or null if on free list */
  466.  
  467.  
  468.  
  469. /***************
  470.  **  Private  **
  471.  **           **
  472.  ***************/
  473.  
  474. static char pvmtxt[512];                /* scratch for error log */
  475. static struct pmsg *rxfrag = 0;            /* not-assembled incm msgs */
  476. static struct frag *rxbuf;                /* buffer for incoming packts */
  477.  
  478. #ifdef IMA_SYMM
  479. static int cpuonline;                    /* the number of CPUs available */
  480. static struct shpage *pvmfraginfo;        /* frag locks and ref counts */
  481. #endif
  482. #ifdef USERECVSEMAPHORE
  483. static int mysemid = -1;                /* ID of semaphore to sleep on */
  484. #endif
  485. static char *pvmdinbox = 0;                /* pvmd's incoming message buffer */
  486. static char *pvmdoutbuf = 0;            /* pvmd's outgoing message buffer */
  487. static int pvminboxsz = 0;                /* size of incoming message buffer */
  488. static int mypidtid = -1;                /* my position in pid-tid table */
  489. static int pvmdpid = 0;                    /* pvmd's Unix proc ID */
  490. static struct sockaddr_in pvmdsad;        /* address of pvmd socket */
  491. static int pvmdsock = -1;                /* pvmd socket descriptor */
  492.  
  493. static void (*pvmoldtermhdlr)() = 0;
  494. static int pvmsettermhdlr = 1;
  495. static int outta_here = 0;
  496.  
  497. /* TT lists used for mcasting [GEF] */
  498. static struct ttpcb *ttlist = 0;        /* dll of connected tasks */
  499. static struct ttpcb *topvmd = 0;        /* default route (to pvmd) */
  500.  
  501.  
  502. /**************************
  503.  **  Internal Functions  **
  504.  **                      **
  505.  **************************/
  506.  
  507. /*    getdsock()
  508. *
  509. *    Get address of pvmd socket, set up pvmdsad.
  510. */
  511.  
  512. void
  513. getdsock()
  514. {
  515.     char buf[128];
  516.     int d;
  517.     int n;
  518.     char *p;
  519.  
  520.     if (!(p = getenv("PVMSOCK"))) {
  521.         if (!(p = pvmdsockfile())) {
  522.             pvmlogerror("getdsock() pvmdsockfile() failed\n");
  523.             return;
  524.         }
  525.         if ((d = open(p, O_RDONLY, 0)) == -1) {
  526.             pvmlogperror(p);
  527.             return;
  528.         }
  529.         n = read(d, buf, sizeof(buf));
  530.         (void)close(d);
  531.         if (n == -1) {
  532.             pvmlogperror("getdsock() read addr file");
  533.             return;
  534.         }
  535.         if (n == 0) {
  536.             pvmlogerror("getdsock() read addr file: wrong length read\n");
  537.             return;
  538.         }
  539.         buf[n] = 0;
  540.         p = buf;
  541.     }
  542.  
  543.     hex_inadport(p, &pvmdsad);
  544.     pvmdsad.sin_family = AF_INET;
  545. }
  546.  
  547.  
  548. /*    prodpvmd()
  549. *
  550. *    wake up the pvmd, which is sleeping on sockets and not shared memory.
  551. *    XXX this sucks.
  552. */
  553.  
  554. void
  555. prodpvmd()
  556. {
  557.     static char dummy[TDFRAGHDR];
  558.  
  559.     if (pvmdsock == -1) {
  560.         if ((pvmdsock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  561.             pvmlogperror("prodpvmd() socket");
  562.             return;
  563.         }
  564.         if (connect(pvmdsock, (struct sockaddr*)&pvmdsad, sizeof(pvmdsad))
  565.         == -1) {
  566.             pvmlogperror("prodpvmd() connect");
  567.             close(pvmdsock);
  568.             pvmdsock = -1;
  569.             return;
  570.         }
  571.         BZERO(dummy, sizeof(dummy));
  572.  
  573.     } else {
  574.         write(pvmdsock, dummy, TDFRAGHDR);
  575.     }
  576. }
  577.  
  578.  
  579. /*    peer_wait()
  580. *
  581. *    Check inbox for messages, block on a semaphore if no message.
  582. */
  583.  
  584. int
  585. peer_wait()
  586. {
  587.     struct msgboxhdr *inbp = (struct msgboxhdr *)pvminbox;
  588.  
  589. #ifndef USERECVSEMAPHORE
  590.  
  591.     PAGELOCK(&inbp->mb_lock);
  592.     while (inbp->mb_read == inbp->mb_last)
  593. #ifdef    IMA_SUNMP
  594.         cond_wait(&inbp->mb_cond, &inbp->mb_lock);
  595. #endif
  596. #if defined(IMA_RS6KMP) || defined(IMA_AIX4MP)
  597.         pthread_cond_wait(&inbp->mb_cond, &inbp->mb_lock);
  598. #endif
  599.     PAGEUNLOCK(&inbp->mb_lock);
  600.  
  601. #else    /*USERECVSEMAPHORE*/
  602.  
  603.     struct sembuf sops;
  604.  
  605.     sops.sem_num = 0;
  606.     sops.sem_op = -1;
  607.     sops.sem_flg = 0;
  608.     while (inbp->mb_read == inbp->mb_last) {
  609.         if (pvmdebmask & PDMSEM) {
  610.             sprintf(pvmtxt, "peer_wait(): Waiting on semop id = %d\n", mysemid);
  611.             pvmlogerror(pvmtxt);
  612.         }
  613.         if (semop(mysemid, &sops, 1) == -1) {
  614.             if (errno != EINTR) {
  615.                 sprintf(pvmtxt, "peer_wait(): Error waiting for semop id = %d",
  616.                         mysemid);
  617.                 pvmlogperror(pvmtxt);
  618.                 return -1;
  619.             }
  620.         }
  621.         else if (pvmdebmask & PDMSEM) {
  622.             sprintf(pvmtxt, "peer_wait(): Processing Event on semop id = %d\n",
  623.                     mysemid);
  624.             pvmlogerror(pvmtxt);
  625.         }
  626.     }
  627.  
  628. #endif    /*USERECVSEMAPHORE*/
  629.     return 0;
  630. }
  631.  
  632.  
  633. /*    pvm_tc_shmat()
  634. *
  635. *    Some Shared Memory Attach Protocol Spanking.
  636. *
  637. *    TC_SHMAT()
  638. */
  639.  
  640. static int
  641. pvm_tc_shmat(mid)
  642.     int mid;
  643. {
  644.     int src;                    /* sender of request */
  645.     int rbf;                    /* rx buffer temp */
  646.     struct peer *pp;
  647.     struct msgboxhdr *dboxp;
  648.     int ackd;                    /* allow connection (0) */
  649.  
  650.     rbf = pvm_setrbuf(mid);
  651.     pvm_bufinfo(mid, (int *)0, (int *)0, &src);
  652.  
  653.     if (!(pp = peer_conn(src, (int *)0)) || pp == (struct peer *)-1L) {
  654.         pvmlogprintf("pvm_tc_shmat() can't connect to src t%x\n", src);
  655.         ackd = -1;
  656.     } else
  657.         ackd = pvmmytid;
  658.     dboxp = (struct msgboxhdr *)pp->p_buf;
  659.     dboxp->mb_attached = ackd;
  660.  
  661.     pvm_setrbuf(rbf);
  662.     pvm_freebuf(mid);
  663.     return 0;
  664. }
  665.  
  666.  
  667. /*    pvm_tc_conreq()
  668. *
  669. *    Another task requests a connection with us.
  670. *    Reply with a TC_CONACK message.
  671. *
  672. *    TC_CONREQ() {
  673. *        int tdprotocol        // t-d protocol revision number
  674. *        string sockaddr        // address of other socket
  675. *    }
  676. */
  677.  
  678. static int
  679. pvm_tc_conreq(mid)
  680.     int mid;
  681. {
  682.     int src;                    /* sender of request */
  683.     int rbf;                    /* rx buffer temp */
  684.     int sbf = 0;                /* reply message mid */
  685.     int ttpro;                    /* protocol revision */
  686.     int ackd;                    /* allow connection (0) */
  687.     int i;
  688.     int ictx;
  689.  
  690.     rbf = pvm_setrbuf(mid);
  691.     pvm_bufinfo(mid, (int *)0, (int *)0, &src);
  692.  
  693.     pvmlogprintf("pvm_tc_conreq() TCP conn request from t%x!\n", src);
  694.  
  695.     sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  696.     ttpro = TDPROTOCOL;
  697.     ackd = 1;
  698.     pvm_pkint(&ttpro, 1, 1);
  699.     pvm_pkint(&ackd, 1, 1);
  700.     pvm_pkstr("");
  701. i = pvmrescode;
  702. pvmrescode = 1;
  703.     ictx = pvm_setcontext(SYSCTX_TC);
  704.     pvm_send(src, TC_CONACK);
  705.     pvm_setcontext(ictx);
  706. pvmrescode = i;
  707.     pvm_freebuf(pvm_setsbuf(sbf));
  708.  
  709.     pvm_setrbuf(rbf);
  710.     pvm_freebuf(mid);
  711.     return 0;
  712. }
  713.  
  714.  
  715. /*    pvm_tc_conack()
  716. *
  717. *    Another task replies to our connection request.
  718. *
  719. *    TC_CONACK() {
  720. *        int tdprotocol        // t-d protocol revision number
  721. *        int ack                // 0 ok, 1 denied
  722. *        string sockaddr        // address of other socket
  723. *    }
  724. */
  725.  
  726. static int
  727. pvm_tc_conack(mid)
  728.     int mid;
  729. {
  730.     int src;                    /* sender of reply */
  731.     int rbf;                    /* rx buffer temp */
  732.  
  733.     rbf = pvm_setrbuf(mid);
  734.     pvm_bufinfo(mid, (int *)0, (int *)0, &src);
  735.  
  736.     pvmlogprintf("pvm_tc_conack() unexpected TC msg from t%x!\n", src);
  737.  
  738.     pvm_setrbuf(rbf);
  739.     pvm_freebuf(mid);
  740.     return 0;
  741. }
  742.  
  743.  
  744. /*    pvm_tc_taskexit()
  745. *
  746. *    We are notified that another task (to which we have a direct route)
  747. *    has exited.
  748. */
  749.  
  750. static int
  751. pvm_tc_taskexit(mid)
  752.     int mid;
  753. {
  754.     int src;                    /* sender of notify */
  755.     int rbf;                    /* rx buffer temp */
  756.     struct peer *pp;
  757.     int found_one = 0;            /* did we find a peer? */
  758.  
  759.     rbf = pvm_setrbuf(mid);
  760.     pvm_bufinfo(mid, (int *)0, (int *)0, &src);
  761.  
  762.  
  763.     if (!outta_here) {
  764.         int tid;
  765.         extern struct peer *peers;
  766.  
  767.         pvm_upkint(&tid, 1, 1);
  768.  
  769.         for (pp = peers->p_link; pp != peers; pp = pp->p_link)
  770.             if (pp->p_tid == tid) {
  771.                 pp->p_exited = 1;        /* mark as deleted */
  772.                 found_one = 1;
  773.                 break;
  774.             }
  775.  
  776.     }
  777.  
  778.     if (!found_one) /* then it was unexpected! */
  779.         pvmlogprintf("pvm_tc_taskexit() unexpected TC msg from t%x!\n", src);
  780.  
  781.     pvm_setrbuf(rbf);
  782.     pvm_freebuf(mid);
  783.     return 0;
  784. }
  785.  
  786.  
  787. /*    mroute()
  788. *
  789. *   Route a message to a destination.
  790. *   Returns when
  791. *       outgoing message (if any) fully sent and
  792. *       (timed out (tmout) or
  793. *           at least one message fully received)
  794. *   Returns >=0 the number of complete messages downloaded, or
  795. *   negative on error.
  796. */
  797.  
  798. int
  799. mroute(mid, dtid, code, tmout)
  800.     int mid;                /* message */
  801.     int dtid;                /* dest */
  802.     int code;                /* type tag */
  803.     struct timeval *tmout;    /* get at least one message */
  804. {
  805.     struct pmsg *txup;            /* tx message or null */
  806.     struct frag *txfp = 0;        /* cur tx frag or null */
  807.     int gotem = 0;                /* count complete msgs downloaded */
  808.     int block;                    /* get at least one message */
  809.     int loopcount = 0;
  810.     struct msgboxhdr *inbp;        /* incoming box */
  811.     struct timeval tnow, tstop;
  812.     int sbf;                    /* reply to control message */
  813.     int cc;
  814.     int freethis = 0;            /* (control) message came from stack */
  815.     int tstkp = 0;
  816.     int tstk[100];                /* XXX shouldn't be a stack */
  817.  
  818.     /* XXX do we really have to do this? */
  819. /*     if ((dtid == TIDPVMD && code == TM_MCA) || dtid == TIDGID) */
  820. /*         return node_mcast(mid, dtid, code); */
  821.  
  822.     if (tmout) {
  823.         if (tmout->tv_sec || tmout->tv_usec) {
  824.             pvmgetclock(&tnow);
  825.             tstop.tv_sec = tnow.tv_sec + tmout->tv_sec;
  826.             tstop.tv_usec = tnow.tv_usec + tmout->tv_usec;
  827.             block = 1;
  828.         } else
  829.             block = 0;
  830.     } else {
  831.         block = 1;
  832.         tstop.tv_sec = -1;
  833.         tstop.tv_usec = -1;
  834.     }
  835.  
  836.     if (txup = midtobuf(mid)) {
  837.         txfp = txup->m_frag->fr_link;
  838.         txfp = txfp->fr_buf ? txfp : 0;
  839.     }
  840.  
  841.     inbp = (struct msgboxhdr *)pvminbox;
  842.  
  843.     do {
  844.         if (block && tstop.tv_sec != -1) {
  845.             pvmgetclock(&tnow);
  846.             if (tnow.tv_sec > tstop.tv_sec
  847.             || (tnow.tv_sec == tstop.tv_sec && tnow.tv_usec >= tstop.tv_usec))
  848.                 break;
  849.         }
  850.  
  851.         if (pvmpolltype == PvmPollSleep
  852.         && loopcount++ > pvmpolltime && !txfp && tstop.tv_sec == -1) {
  853.             PAGELOCK(&inbp->mb_lock);
  854.             if (inbp->mb_read == inbp->mb_last) {
  855.                 inbp->mb_sleep = 1;
  856.                 PAGEUNLOCK(&inbp->mb_lock);
  857.                 if (peer_wait() == -1)
  858.                     return PvmSysErr;
  859.                 loopcount = 0;
  860.             } else
  861.                 PAGEUNLOCK(&inbp->mb_lock);
  862.         }
  863.  
  864.         if (inbp->mb_read != inbp->mb_last) {
  865.             if ((sbf = peer_recv(&gotem)) == -1)
  866.                 return PvmSysErr;
  867.             if (sbf > 0) {
  868.                 if (txfp)
  869.                     tstk[tstkp++] = sbf;
  870.                 else {
  871.                     txup = midtobuf(sbf);
  872.                     dtid = txup->m_dst;
  873.                     code = txup->m_tag;
  874.                     txfp = txup->m_frag->fr_link;
  875.                     txfp = txfp->fr_buf ? txfp : 0;
  876.                     freethis = 1;
  877.                 }
  878.             }
  879.         }
  880.  
  881.         if (txfp) {
  882.             if ((cc = peer_send(txup, txfp, dtid, code)) < 0)
  883.                 return cc;
  884.             if (cc) {
  885.                 txfp = txfp->fr_link;
  886.                 if (!txfp->fr_buf) {
  887.                     if (freethis)
  888.                         umbuf_free(txup);
  889.                     if (tstkp > 0) {
  890.                         txup = midtobuf(tstk[--tstkp]);
  891.                         dtid = txup->m_dst;
  892.                         code = txup->m_tag;
  893.                         txfp = txup->m_frag->fr_link;
  894.                         txfp = txfp->fr_buf ? txfp : 0;
  895.                         freethis = 1;
  896.                     } else
  897.                         txfp = 0;
  898.                 }
  899.             }
  900.         }
  901.  
  902.     } while (txfp || (block && !gotem));
  903.  
  904.     return gotem;
  905. }
  906.  
  907.  
  908.  
  909. /*    peer_recv()
  910. *
  911. *    Receive a message fragment from another task.
  912. *    Reassemble frags into messages and place on rxlist.
  913. *    On completing a control message, call mesg_input(),
  914. *        which consumes it.
  915. *    Returns:
  916. *        0 normally,
  917. *        negative if error,
  918. *        or message handle of a reply control message to be sent.
  919. */
  920.  
  921. int
  922. peer_recv(gotem)
  923.     int *gotem;
  924. {
  925.     struct pmsg *rxup;            /* rx message */
  926.     struct pmsg *up;
  927.     struct frag *fp;
  928.     int sdr;
  929.     int src;
  930.     int ff;
  931.     struct peer *pp = 0;
  932.     int next;                    /* frag being received */
  933.     struct shmpkhdr *inmsgs;    /* incoming messages */
  934.     struct msgboxhdr *inbp;        /* incoming box */
  935.     int sbf = 0;                /* reply control message */
  936.  
  937.     inbp = (struct msgboxhdr *)pvminbox;
  938.     inmsgs = (struct shmpkhdr *)(inbp + 1);
  939.  
  940.     next = (inbp->mb_read + 1) % pvminboxsz;
  941.     sdr = inmsgs[next].ph_sdr;
  942.     fp = fr_new(0);
  943.     if ((sdr & ~pvmtidhmask) != TIDPVMD) {
  944.         if (!(pp = peer_conn(sdr, (int *)0)) || pp == (struct peer *)-1L) {
  945.             sprintf(pvmtxt, "peer_recv() can't connect to sender t%x\n", sdr);
  946.             pvmlogerror(pvmtxt);
  947.             return PvmSysErr;
  948.         }
  949.         fp->fr_dat = pp->p_buf + INBOXPAGE*pgsz + inmsgs[next].ph_dat;
  950.     } else
  951.         fp->fr_dat = pvmdoutbuf + inmsgs[next].ph_dat;
  952.     fp->fr_buf = fp->fr_dat - (inmsgs[next].ph_dat & (pgsz-1))
  953.                 + PVMPAGEHDR;
  954.     fp->fr_max = pvmfrgsiz;
  955.     ff = inmsgs[next].ph_flag;
  956.  
  957.     src = inmsgs[next].ph_src;
  958.     fp->fr_len = inmsgs[next].ph_len;
  959.     fp->fr_max = pvmfrgsiz;
  960.  
  961.     if (pvmdebmask & PDMPACKET) {
  962.         sprintf(pvmtxt, "peer_recv() sdr t%x src t%x len %d dst t%x flag %d\n",
  963.             sdr, src, fp->fr_len, inmsgs[next].ph_dst, ff);
  964.         pvmlogerror(pvmtxt);
  965.     }
  966.  
  967.     /*
  968.     * if start of message, make new umbuf, add to frag pile
  969.     */
  970.     if (ff & FFSOM) {
  971.         rxup = umbuf_new();
  972.         rxup->m_tag = inmsgs[next].ph_tag;
  973.         rxup->m_ctx = inmsgs[next].ph_ctx;
  974.         rxup->m_enc = inmsgs[next].ph_enc;
  975.         rxup->m_wid = inmsgs[next].ph_wid;
  976.         rxup->m_crc = inmsgs[next].ph_crc;
  977.         rxup->m_src = src;
  978. #ifdef IMA_CSPP
  979.         if (pp && pp->p_node != current_node())
  980.             rxup->m_flag |= UB_DIFFNODE;
  981. #endif
  982.         LISTPUTBEFORE(rxfrag, rxup, m_link, m_rlink);
  983.     }
  984.  
  985.     /* locate frag's message */
  986.  
  987.     for (rxup = rxfrag->m_link; rxup != rxfrag; rxup = rxup->m_link)
  988.         if (rxup->m_src == src)
  989.             break;
  990.  
  991.     if (rxup == rxfrag) {    /* uh oh, no message for it */
  992.         pvmlogerror("peer_recv() frag with no message\n");
  993.         fr_unref(fp);
  994.  
  995.     } else {
  996.         LISTPUTBEFORE(rxup->m_frag, fp, fr_link, fr_rlink);
  997.         rxup->m_len += fp->fr_len;
  998.     /*
  999.     * if end of message, move to rxlist and count it
  1000.     */
  1001.         if (ff & FFEOM) {
  1002.             LISTDELETE(rxup, m_link, m_rlink);
  1003. #ifdef    MCHECKSUM
  1004.             if (rxup->m_crc != umbuf_crc(rxup)) {
  1005.                 sprintf(pvmtxt,
  1006.                 "peer_recv() message src t%x tag %d bad checksum\n",
  1007.                         rxup->m_src, rxup->m_tag);
  1008.                 pvmlogerror(pvmtxt);
  1009.                 umbuf_free(rxup);
  1010.  
  1011.             } else {
  1012. #endif
  1013.                 pmsg_setenc(rxup, rxup->m_enc);
  1014.                 mesg_input(rxup);
  1015.                 (*gotem)++;
  1016. #ifdef    MCHECKSUM
  1017.             }
  1018. #endif
  1019.         }
  1020.     }
  1021.     inbp->mb_read = next;
  1022.     return sbf;
  1023. }
  1024.  
  1025.  
  1026. /*    peer_send()
  1027. *
  1028. *    Send fragment to another process.
  1029. *    Establish connection if necessary, exchange handshake message.
  1030. *
  1031. *    Returns 1 if sent, 0 otherwise, negative on error.
  1032. */
  1033.  
  1034. int
  1035. peer_send(txup, txfp, dtid, code)
  1036.     struct pmsg *txup;        /* tx message or null */
  1037.     struct frag *txfp;        /* cur tx frag or null */
  1038.     int dtid;                /* dest */
  1039.     int code;                /* type code */
  1040. {
  1041.     char *cp = 0;                /* points to copy-databuf (if necessary) */
  1042.     int ff;
  1043.     int loc;                    /* location of data in shared segment */
  1044.     int next;                    /* frag being received */
  1045.     struct peer *pp;
  1046.     struct shmpkhdr *dmsgs;
  1047.     struct msgboxhdr *dboxp;    /* receiving box of peer */
  1048.  
  1049.     if (!txfp->fr_u.dab) {
  1050.         pvmlogerror("peer_send() PvmDataInPlace not implemented\n");
  1051.         return PvmNotImpl;
  1052.     }
  1053.  
  1054.     /* If its a control message always pass via the daemon */
  1055.     /* This avoids the I'cant send to you as you haven't handled my */
  1056.     /* tc_shmat handshake *message* yet problem... it was the chicken first */
  1057.     /* why? because the daemon is connected as beatask() has worked (maybe) */
  1058.  
  1059.     if (((dtid & pvmtidhmask) == (pvmmytid & pvmtidhmask)
  1060.     && (dtid & ~pvmtidhmask) != TIDPVMD) /* to local task */
  1061.     && !(code>=TC_FIRST && code<=TC_LAST) )    /* and not a CTRL TC message */
  1062.     {
  1063.         int new_connection;
  1064.  
  1065.         if (!(pp = peer_conn(dtid, &new_connection)))
  1066.             return 0;
  1067.         if (pp != (struct peer *)-1L) {
  1068.             dboxp = (struct msgboxhdr *)pp->p_buf;
  1069.             if (new_connection) {
  1070.                 struct pmsg *mp;
  1071.                 int sbf, l;
  1072.                 struct msgboxhdr *inbp = (struct msgboxhdr *)pvminbox;
  1073.                 static struct timeval ztv = { 0, 0 };
  1074.  
  1075.                 sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  1076.                 l = TDPROTOCOL;
  1077.                 pvm_pkint(&l, 1, 1);
  1078.                 sbf = pvm_setsbuf(sbf);
  1079.                 inbp->mb_attached = 0;
  1080.     /* XXX glggg, could we just return to mroute here instead of calling it? */
  1081.                 mp = midtobuf(sbf);
  1082.                 mp->m_ctx = SYSCTX_TC;
  1083.                 mroute(sbf, dtid, TC_SHMAT, &ztv);
  1084.                 pvm_freebuf(sbf);
  1085.                  while (!inbp->mb_attached)  
  1086.                     mroute(0, 0, 0, &ztv);        /* avoid deadlock */
  1087.                 if (inbp->mb_attached != dtid) {
  1088.                     sprintf(pvmtxt,
  1089.                         "peer_send: mb_attached: expected %x, got %x\n",
  1090.                         dtid, inbp->mb_attached);
  1091.                     pvmlogerror(pvmtxt);
  1092.                 }
  1093.             }
  1094.  
  1095.         } else
  1096.             dboxp = (struct msgboxhdr *)pvmdinbox;
  1097.     } else
  1098.         dboxp = (struct msgboxhdr *)pvmdinbox;
  1099.  
  1100.     if ((dboxp->mb_last + 1) % pvminboxsz == dboxp->mb_read)
  1101.         return 0;        /* full */
  1102.  
  1103.     /*
  1104.     * if page is private, copy and replace it with one in shared buf
  1105.     */
  1106.  
  1107.     if ((loc = txfp->fr_dat - outmsgbuf) > outbufsz * pvmpgsz || loc < 0) {
  1108.         if (nbufsowned == outbufsz) {
  1109.             int i;
  1110.  
  1111.             pvmlogerror("peer_send() Message(s) too long for shared buffer, deadlocked.\n");
  1112.             PAGELOCK(&((struct shmpghdr *)infopage)->pg_lock);
  1113.             for (i = 0; i < maxpidtid; i++)
  1114.                 if (pidtids[i].pt_tid == pvmmytid) {
  1115.                     pidtids[i].pt_cond = 1;
  1116.                     break;
  1117.                 }
  1118.             PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock);
  1119.         }
  1120.  
  1121.         cp = 0;
  1122.         do {
  1123.             if (cp)
  1124.                 da_unref(cp);
  1125.             cp = da_new(MAXHDR + txfp->fr_len);
  1126.         } while ((loc = cp - outmsgbuf + MAXHDR) > outbufsz*pvmpgsz || loc < 0);
  1127.  
  1128.         BCOPY(txfp->fr_dat, cp + MAXHDR, txfp->fr_len);
  1129.         txfp->fr_dat = cp + MAXHDR;
  1130.         da_unref(txfp->fr_buf);
  1131.         txfp->fr_buf = cp;
  1132.     }
  1133.  
  1134.     if (txfp->fr_rlink == txup->m_frag)
  1135.         ff = FFSOM;
  1136.     else
  1137.         ff = 0;
  1138.     if (txfp->fr_link == txup->m_frag)
  1139.         ff |= FFEOM;
  1140.  
  1141.     if (pvmdebmask & PDMPACKET) {
  1142.         sprintf(pvmtxt, "peer_send() dst t%x len %d page %d flag %d\n",
  1143.             dtid, txfp->fr_len, loc/pgsz + 1, ff);
  1144.         pvmlogerror(pvmtxt);
  1145.     }
  1146.  
  1147.     dmsgs = (struct shmpkhdr *)(dboxp + 1);
  1148.     PAGELOCK(&dboxp->mb_lock);
  1149.     next = (dboxp->mb_last + 1) % pvminboxsz;
  1150.     /* if receive buffer full, must fail here and try again - sgi:jpb */
  1151.     if ( next == dboxp->mb_read ) {        /* full */
  1152.         PAGEUNLOCK(&dboxp->mb_lock);
  1153.         return 0;
  1154.     }
  1155.     dmsgs[next].ph_src = pvmmytid;
  1156.     dmsgs[next].ph_dst = dtid;
  1157.     dmsgs[next].ph_sdr = pvmmytid;
  1158.     dmsgs[next].ph_dat = loc;
  1159.     dmsgs[next].ph_len = txfp->fr_len;
  1160.     dmsgs[next].ph_flag = ff;
  1161.     if (ff & FFSOM) {
  1162.         dmsgs[next].ph_tag = code;
  1163.         dmsgs[next].ph_ctx = txup->m_ctx;
  1164.         dmsgs[next].ph_enc = txup->m_enc;
  1165.         dmsgs[next].ph_wid = txup->m_wid;
  1166. #ifdef    MCHECKSUM
  1167.         dmsgs[next].ph_crc = umbuf_crc(txup);
  1168. #else
  1169.         dmsgs[next].ph_crc = 0;
  1170. #endif
  1171.         if (pvmdebmask & PDMMESSAGE) {
  1172.             sprintf(pvmtxt, "peer_send() dst t%x tag %s ctx %d\n",
  1173.                 dtid, pvmnametag(dmsgs[next].ph_tag,(int*)0), 
  1174.                 dmsgs[next].ph_ctx);
  1175.             pvmlogerror(pvmtxt);
  1176.         } /* logging */
  1177.  
  1178.     } else {
  1179.         dmsgs[next].ph_tag = 0;
  1180.         dmsgs[next].ph_ctx = 0;
  1181.         dmsgs[next].ph_enc = 0;
  1182.         dmsgs[next].ph_wid = 0;
  1183.         dmsgs[next].ph_crc = 0;
  1184.     }
  1185.     da_ref(txfp->fr_buf);
  1186.     dboxp->mb_last = next;
  1187.  
  1188.     if (dboxp != (struct msgboxhdr *)pvmdinbox && dboxp->mb_sleep) {
  1189. #if    defined(IMA_SUNMP) || defined(IMA_RS6KMP) || defined(IMA_AIX4MP)
  1190. #ifdef    IMA_SUNMP
  1191.         cond_signal(&dboxp->mb_cond);
  1192. #endif
  1193. #if defined(IMA_RS6KMP) || defined(IMA_AIX4MP)
  1194.         pthread_cond_signal(&dboxp->mb_cond);
  1195. #endif
  1196. #else
  1197.         peer_wake(pp);
  1198. #endif
  1199.         dboxp->mb_sleep = 0;
  1200.     }
  1201.  
  1202.     /* wake up pvmd */
  1203.  
  1204.     if (dboxp == (struct msgboxhdr *)pvmdinbox
  1205.     && (dboxp->mb_last + pvminboxsz - 1) % pvminboxsz == dboxp->mb_read) {
  1206.         PAGEUNLOCK(&dboxp->mb_lock);
  1207.         (void)prodpvmd();
  1208.     } else
  1209.         PAGEUNLOCK(&dboxp->mb_lock);
  1210.  
  1211.     return 1;
  1212. }
  1213.  
  1214.  
  1215. int
  1216. node_mcast(mid, dtid, code)
  1217.     int mid;    /* message id */
  1218.     int dtid;    /* destination */
  1219.     int code;    /* type */
  1220. {
  1221.     static int *tids = 0;    /* intended recipients of multicast message */
  1222.     static int ntids = -1;
  1223.     static int ntask;        /* number of tids */
  1224.     static struct timeval ztv = { 0, 0 };
  1225.  
  1226.     int i;
  1227.     long count = 0;
  1228.     int cc = 0;
  1229.     int dummy;
  1230.  
  1231.     /* intercept multicast info */
  1232.  
  1233.     if (dtid == TIDPVMD) {
  1234.         int sbf = mid;
  1235.  
  1236.         pvm_setrbuf(mid);
  1237.         pvm_upkint(&ntask, 1, 1);
  1238.         if (ntask > ntids) {
  1239.             if (tids)
  1240.                 PVM_FREE(tids);
  1241.             tids = TALLOC(ntask, int, "tids");
  1242.             ntids = ntask;
  1243.         }
  1244.         pvm_upkint(tids, ntask, 1);
  1245.         /* sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo)); */
  1246.         pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  1247.         dummy = TIDGID;
  1248.         pvm_pkint(&dummy, 1, 1);
  1249.         pvm_setrbuf(pvm_setsbuf(sbf));
  1250.         return 0;
  1251.     }
  1252.  
  1253.     for (i = 0; i < ntask; i++)
  1254.         if (tids[i] != pvmmytid)
  1255.             cc = mroute(mid, tids[i], code, &ztv);
  1256.  
  1257.     ntask = 0;
  1258.  
  1259.     return cc;
  1260. }
  1261.  
  1262.  
  1263. /*    msendrecv()
  1264. *
  1265. *    Single op to send a system message (usually to our pvmd) and get
  1266. *    the reply.
  1267. *    Returns message handle or negative if error.
  1268. */
  1269.  
  1270. int
  1271. msendrecv(other, code, context)
  1272.     int other;                /* dst, src tid */
  1273.     int code;                /* message tag */
  1274.     int context;            /* context to use for the message */
  1275. {
  1276.     static int nextwaitid = 1;    /* I hope */
  1277.  
  1278.     int cc;
  1279.     struct pmsg *up;
  1280.  
  1281.     if (!pvmsbuf)
  1282.         return PvmNoBuf;
  1283.  
  1284.     /* send code to other */
  1285.     if (pvmdebmask & PDMMESSAGE) {
  1286.         sprintf(pvmtxt, "msendrecv() to t%x tag %s\n", other,
  1287.                 pvmnametag(code, (int *)0));
  1288.         pvmlogerror(pvmtxt);
  1289.     }
  1290.  
  1291.    pvmsbuf->m_wid = nextwaitid++;
  1292.    pvmsbuf->m_ctx = context;
  1293.  
  1294.    if ((cc = mroute(pvmsbuf->m_mid, other, code, (struct timeval *)0)) < 0)
  1295.         return cc;
  1296.  
  1297.     /* Oops now what? */
  1298.     /*     if (code == TM_MCA)         */
  1299.         /* for node_mcast() */
  1300.     /*         return 1; */
  1301.  
  1302.     /* recv code from other */
  1303.     for (up = pvmrxlist->m_link; 1; up = up->m_link) {
  1304.         if (up == pvmrxlist) {
  1305.             up = up->m_rlink;
  1306.             if ((cc = mroute(0, 0, 0, (struct timeval *)0)) < 0)
  1307.                 return cc;
  1308.             up = up->m_link;
  1309.         }
  1310.  
  1311.         if (pvmdebmask & PDMMESSAGE) {
  1312.             sprintf(pvmtxt, "msendrecv() from t%x tag %s\n",
  1313.                     up->m_src, pvmnametag(up->m_tag, (int *)0));
  1314.             pvmlogerror(pvmtxt);
  1315.         }
  1316.         if (up->m_src == other && up->m_tag == code)
  1317.             break;
  1318.     }
  1319.     LISTDELETE(up, m_link, m_rlink);
  1320.     if (pvmrbuf)
  1321.         umbuf_free(pvmrbuf);
  1322.     pvmrbuf = 0;
  1323.     if (cc = pvm_setrbuf(up->m_mid))
  1324.         return cc;
  1325.     return up->m_mid;
  1326. }
  1327.  
  1328.  
  1329. static void
  1330. catch_kill(sig)
  1331.     int sig;
  1332. {
  1333.     signal(SIGTERM, pvmoldtermhdlr);
  1334.     if (pvmoldtermhdlr && pvmoldtermhdlr != SIG_IGN)
  1335.         pvmoldtermhdlr(sig);
  1336.     /* XXX yes, i know the table isn't locked.  we're in a sighandler */
  1337.     if (pidtids && pidtids[mypidtid].pt_stat != ST_EXIT)
  1338.         pidtids[mypidtid].pt_stat = ST_FINISH;
  1339.     pvmendtask();
  1340.     exit(sig);
  1341. }
  1342.  
  1343.  
  1344. static int
  1345. read_int(val)
  1346.     int *val;
  1347. {
  1348.     return *val;
  1349. }
  1350.  
  1351.  
  1352. /*    pvmbeatask()
  1353. *
  1354. *    Initialize libpvm, config process as a task.
  1355. *    This is called as the first step of each libpvm function so no
  1356. *    explicit initialization is required.
  1357. *
  1358. *    Returns 0 if okay, else error code.
  1359. *
  1360. *    XXX needs work.  lots of inconsistent state is left on error return.
  1361. *    I'm working on it
  1362. */
  1363.  
  1364. int
  1365. pvmbeatask()
  1366. {
  1367.     struct shmpkhdr *inmsgs;
  1368.     struct pidtidhdr *pvminfo;
  1369.     struct msgboxhdr *dboxp;        /* receiving box of pvmd */
  1370.     int next;
  1371.     int altpid;                        /* pid of ancestor forked by pvmd */
  1372.     int msgcnt;
  1373.     char *msgbuf;                    /* my message buffer */
  1374.     int bufid;
  1375.     int i;
  1376.     int pid;
  1377.     int bid;
  1378.     int rc;
  1379.     char *p;
  1380.     struct pvmminfo minfo;
  1381.     int cc = 0;
  1382.     int sbf = 0, rbf = 0;            /* saved rx and tx message handles */
  1383.     int outtid, outctx, outtag;
  1384.     int trctid, trcctx, trctag;
  1385.     int need_trcinfo = 0;
  1386.     int new_tracer = 0;
  1387.     char tmask[ 2 * TEV_MASK_LENGTH ];
  1388.     int tbuf, topt;
  1389.     int mid;
  1390. /*
  1391.     union semun {
  1392.         int val;
  1393.         struct semid_ds *buf;
  1394.         ushort *array;
  1395.     } sunion;
  1396. */
  1397. #ifdef LOG
  1398.     char fname[32];
  1399. #endif
  1400.     int key, firstkeytried;
  1401.     int mytid;
  1402.     TEV_DECLS
  1403.  
  1404.     if (pvmmytid != -1)
  1405.         return 0;
  1406.  
  1407.     pvmmydsig = pvmgetdsig();
  1408.  
  1409.     TEV_EXCLUSIVE;
  1410.  
  1411.     if ((pvm_useruid = getuid()) == -1) {
  1412.         pvmlogerror("pvmbeatask() can't getuid()\n");
  1413.         return PvmSysErr;
  1414.     }
  1415.  
  1416.     if (p = getenv("PVMTASKDEBUG")) {
  1417.         pvmdebmask = pvmxtoi(p);
  1418.         if (pvmdebmask) {
  1419.             sprintf(pvmtxt,"task debug mask is 0x%x\n", pvmdebmask);
  1420.             pvmlogerror(pvmtxt);
  1421.         }
  1422.     }
  1423.  
  1424.     pvmmyupid = getpid();
  1425.  
  1426. #ifdef LOG
  1427. #ifdef IMA_CSPP
  1428.     int scid = get_scid();
  1429.  
  1430.     if (scid > 1)
  1431.         sprintf(fname, "/tmp/pvmt.%d.%d", pvm_useruid, scid);
  1432.     else
  1433. #endif
  1434.         sprintf(fname, "/tmp/pvmt.%d", pvm_useruid);
  1435.         if ((logfp = fopen(fname, "a")) == NULL)
  1436.             pvmlogerror("pvmbeatask() can't open log file\n");
  1437. #endif
  1438.  
  1439.     /*
  1440.     * get expected pid from environment in case we were started by
  1441.     * the pvmd and someone forked again
  1442.     */
  1443.  
  1444.     if (p = getenv("PVMEPID"))
  1445.         altpid = atoi(p);
  1446.     else
  1447.         altpid = 0;
  1448.  
  1449.     pgsz = sysconf(_SC_PAGESIZE);
  1450.     pvmpgsz = FRAGPAGE*pgsz;
  1451.     pvmfrgsiz = pvmpgsz - PVMPAGEHDR;
  1452.     pvminboxsz =
  1453.         (INBOXPAGE*pgsz - sizeof(struct msgboxhdr))/sizeof(struct shmpkhdr);
  1454.  
  1455.     /*
  1456.     *    initialize received-message list and fragment reassembly list
  1457.     */
  1458.  
  1459.     rxfrag = pmsg_new(1);
  1460.     BZERO((char*)rxfrag, sizeof(struct pmsg));
  1461.     rxfrag->m_link = rxfrag->m_rlink = rxfrag;
  1462.  
  1463.     pvmrxlist = pmsg_new(1);
  1464.     BZERO((char*)pvmrxlist, sizeof(struct pmsg));
  1465.     pvmrxlist->m_link = pvmrxlist->m_rlink = pvmrxlist;
  1466.  
  1467.     peer_init();
  1468.  
  1469.     /*
  1470.     * SIGTERM handler to clean up our shared memory
  1471.     */
  1472.  
  1473.     if (pvmsettermhdlr) {
  1474.         pvmoldtermhdlr = signal(SIGTERM, catch_kill);
  1475.         pvmsettermhdlr = 0;
  1476.     }
  1477.  
  1478.     /*
  1479.     * get pvmd's message buffer, check protocol revision
  1480.     */
  1481.  
  1482.     key = pvmshmkey(0);
  1483.     if ((bufid = shmget((key_t)key, 0, PERMS)) == -1) {
  1484.         pvmlogperror("pvmbeatask() shmget: can't connect to pvmd");
  1485.         return PvmSysErr;
  1486.     }
  1487.     if ((pvmdinbox = (char *)shmat(bufid, 0, 0)) == (char *)-1L) {
  1488.         pvmlogperror("pvmbeatask() shmat pvmd");
  1489.         return PvmSysErr;
  1490.     }
  1491.     infopage = pvmdinbox + INBOXPAGE*pgsz;
  1492.     pvmdoutbuf = infopage + pgsz;
  1493.  
  1494.     pvminfo = (struct pidtidhdr *)(infopage + PVMPAGEHDR);
  1495.  
  1496.     while ( read_int( (int *) &(pvminfo[0]) ) == 0 ) {
  1497.         sleep(1);
  1498.         if (pvmdebmask & PDMMEM)
  1499.             pvmlogerror("Waiting for pvmd to set protocol\n");
  1500.     }
  1501.     if (pvminfo->i_proto != TDPROTOCOL) {
  1502.         sprintf(pvmtxt, "beatask() t-d protocol mismatch (%d/%d)\n",
  1503.             TDPROTOCOL, pvminfo[0]);
  1504.         pvmlogerror(pvmtxt);
  1505.         return PvmSysErr;
  1506.     }
  1507.  
  1508.     /*
  1509.     * send it a request for connection/task assignment
  1510.     */
  1511.  
  1512.     dboxp = (struct msgboxhdr *)pvmdinbox;
  1513.     inmsgs = (struct shmpkhdr *)(dboxp + 1);
  1514.     PAGELOCK(&dboxp->mb_lock);
  1515.     while ((next = (dboxp->mb_last + 1) % pvminboxsz) == dboxp->mb_read) ;
  1516.     /* XXX yuck, overloading these fields */
  1517.     inmsgs[next].ph_src = pvmmyupid;
  1518.     inmsgs[next].ph_dst = altpid;
  1519.     inmsgs[next].ph_dat = -1;
  1520.     inmsgs[next].ph_sdr = 0;
  1521.     inmsgs[next].ph_len = 0;
  1522.     inmsgs[next].ph_flag = 0;
  1523.     inmsgs[next].ph_tag = 0;
  1524.     inmsgs[next].ph_enc = 0;
  1525.     inmsgs[next].ph_wid = 0;
  1526.     inmsgs[next].ph_crc = 0;
  1527.     dboxp->mb_last = next;
  1528.     PAGEUNLOCK(&dboxp->mb_lock);
  1529.  
  1530.     pvmdpid = pvminfo->i_dpid;
  1531.     (void)getdsock();
  1532.  
  1533.     PAGELOCK(&dboxp->mb_lock);
  1534.     if ((next - 1) % pvminboxsz == dboxp->mb_read) {
  1535.         PAGEUNLOCK(&dboxp->mb_lock);
  1536.         (void)prodpvmd();
  1537.     } else
  1538.         PAGEUNLOCK(&dboxp->mb_lock);
  1539.  
  1540.  
  1541.     /*
  1542.     * get global parameters from pvmd buffer
  1543.     */
  1544.  
  1545. /*
  1546.     pvmmydsig = pvminfo->i_dsig;
  1547. */
  1548.     shmbufsiz = pvminfo->i_bufsiz;
  1549.     outbufsz = (shmbufsiz - INBOXPAGE*pgsz)/pvmpgsz;
  1550.     nbufsowned = 0;
  1551.     pidtids = (struct pidtid *)(pvminfo + 1);
  1552.     maxpidtid = (pgsz - sizeof(struct pidtidhdr) - PVMPAGEHDR)/sizeof(struct pidtid);
  1553.  
  1554.     /*
  1555.     * wait for pvmd to write us an entry in pidtid table
  1556.     */
  1557.  
  1558.     pid = altpid ? altpid : pvmmyupid;
  1559.     mytid = -1;
  1560.     while (mytid == -1) {
  1561.         int ntids;            /* number of entries in pid-tid table */
  1562.  
  1563.         PAGELOCK(&((struct shmpghdr *)infopage)->pg_lock);
  1564.         ntids = min(maxpidtid, ((struct shmpghdr *)infopage)->pg_ref);
  1565.         for (i = 0; i < ntids; i++)
  1566.             if (pidtids[i].pt_pid == pid) {
  1567.                 mytid = pidtids[i].pt_tid;
  1568.                 pvmmyptid = pidtids[i].pt_ptid;
  1569.                 /* pidtids[i].pt_pid = pvmmyupid; */
  1570.                 mypidtid = i;
  1571.                 break;
  1572.             }
  1573.         PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock);
  1574.         if (mytid==-1) { /* not entered in pvmd info page yet */
  1575.             prodpvmd();    /* kick daemon out of select() in work() */
  1576.             sleep_dammit( 10000 );    /* prevent peer page lock race */
  1577.                                     /* on info page */
  1578.         }
  1579.     }
  1580.  
  1581.  
  1582.     /*
  1583.     * create shared memory segment (and semaphore)
  1584.     * if we can't get the first key, keep trying others
  1585.     * XXX this could be moved back to after the protocol num check.
  1586.     */
  1587.  
  1588.     firstkeytried = key = pvmshmkey(getpid());
  1589.     while (1) {
  1590.  
  1591. /* moved here from down there */
  1592. myshmbufid = -1;
  1593. errno = ENOSPC;
  1594. /* static int once = 0; */
  1595. /* if (once > 3) */
  1596.         myshmbufid = shmget((key_t)key, shmbufsiz, IPC_CREAT|IPC_EXCL|PERMS);
  1597. /* else { */
  1598. /* myshmbufid = -1; */
  1599. /* errno = ENOSPC; */
  1600. /* once++; */
  1601. /* } */
  1602.         if (myshmbufid == -1) {
  1603.             if (errno != EACCES && errno != EEXIST) {
  1604.                 pvmlogperror("pvmbeatask() shmget");
  1605.                 return PvmSysErr;
  1606.             }
  1607.  
  1608.         } else {
  1609. #ifdef    USERECVSEMAPHORE
  1610.             mysemid = semget((key_t)key, 1, IPC_CREAT|IPC_EXCL|PERMS);
  1611.             if (mysemid == -1) {
  1612.                 if (errno != EACCES && errno != EEXIST) {
  1613.                     pvmlogperror("pvmbeatask() semget");
  1614.                     shmctl(myshmbufid, IPC_RMID, (struct shmid_ds *)0);
  1615.                     return PvmSysErr;
  1616.  
  1617.                 } else {
  1618.                     shmctl(myshmbufid, IPC_RMID, (struct shmid_ds *)0);
  1619.                 }
  1620.  
  1621.             } else {
  1622. /*
  1623.                 sunion.val = 0;
  1624.                 if (semctl(mysemid, 0, SETVAL, sunion) == -1) {
  1625.                     pvmlogperror("pvmbeatask() semctl SETVAL");
  1626.                     return PvmSysErr;
  1627.                 }
  1628. */
  1629.                 break;
  1630.             }
  1631. #else
  1632.             break;
  1633. #endif
  1634.         }
  1635.  
  1636.         key = nextpvmshmkey(key);
  1637.         if (key == firstkeytried) {
  1638.             pvmlogerror("pvmbeatask() can't find a free key!\n");
  1639.             return PvmSysErr;
  1640.         }
  1641.     }
  1642.  
  1643. #ifdef IMA_CSPP
  1644.     if ((pvminbox = (char *)shm_search(myshmbufid)) == (char *)-1L)
  1645. #else
  1646.     if ((pvminbox = (char *)shmat(myshmbufid, 0, 0)) == (char *)-1L)
  1647. #endif
  1648.     {
  1649.         pvmlogperror("pvmbeatask() shmat");
  1650.         shmctl(myshmbufid, IPC_RMID, (struct shmid_ds *)0);
  1651.         return PvmSysErr;
  1652.     }
  1653.  
  1654.     outmsgbuf = pvminbox + INBOXPAGE*pgsz;
  1655.     msgbufinit(pvminbox);
  1656.     /* XXX PAGELOCK(pvminfo); */
  1657.     pidtids[mypidtid].pt_key = key;
  1658.     pidtids[mypidtid].pt_stat = ST_SHMEM;
  1659. #ifdef IMA_CSPP
  1660.     pidtids[mypidtid].pt_node = current_node();
  1661. #endif
  1662.     /* XXX PAGEUNLOCK(pvminfo); */
  1663.  
  1664.     pvmmytid = mytid;
  1665.  
  1666.     /* OK..
  1667.      * Daemon has been prodded... so lets give it our Unix pid via
  1668.      * the socket so it can match the socket to the process.
  1669.      * That way, when the socket goes EOF pvmd knows which process
  1670.      * it was....
  1671.      * Note we call it this late so that pmsg buffers are available.
  1672.      * Although the message is constructed in shmem its sent via the
  1673.      * socket!
  1674.      */
  1675.  
  1676.     send_my_pid();
  1677.  
  1678.  
  1679.     /*
  1680.     *    Request task trace/output paramters from daemon
  1681.     */
  1682.  
  1683.     sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  1684.     rbf = pvm_setrbuf(0);
  1685.     if ((cc = msendrecv(TIDPVMD, TM_GETOPT, SYSCTX_TM)) > 0) {
  1686.         pvm_upkint(&rc, 1, 1);    /* throw out tid, ptid */
  1687.         pvm_upkint(&rc, 1, 1);
  1688.  
  1689.         pvm_upkint(&outtid, 1, 1);
  1690.         pvm_upkint(&outctx, 1, 1);
  1691.         pvm_upkint(&outtag, 1, 1);
  1692.         if (!pvmtrc.outtid) {
  1693.             pvmtrc.outtid = outtid;
  1694.             pvmtrc.outctx = outctx;
  1695.             pvmtrc.outtag = outtag;
  1696.             pvmctrc.outtid = pvmtrc.outtid;
  1697.             pvmctrc.outctx = pvmtrc.outctx;
  1698.             pvmctrc.outtag = pvmtrc.outtag;
  1699.         }
  1700.  
  1701.         pvm_upkint(&trctid, 1, 1);
  1702.         pvm_upkint(&trcctx, 1, 1);
  1703.         pvm_upkint(&trctag, 1, 1);
  1704.         if (!pvmtrc.trctid) {
  1705.             pvmtrc.trctid = trctid;
  1706.             pvmtrc.trcctx = trcctx;
  1707.             pvmtrc.trctag = trctag;
  1708.             pvmctrc.trctid = pvmtrc.trctid;
  1709.             pvmctrc.trcctx = pvmtrc.trcctx;
  1710.             pvmctrc.trctag = pvmtrc.trctag;
  1711.             new_tracer++;
  1712.         }
  1713.  
  1714.         cc = 0;
  1715.     }
  1716.     pvm_freebuf(pvm_setrbuf(rbf));
  1717.     pvm_freebuf(pvm_setsbuf(sbf));
  1718.  
  1719.     if (p = getenv("PVMCTX"))
  1720.         pvmmyctx = pvmstrtoi(p);
  1721.  
  1722.     /* get trace mask from envar or zero it */
  1723.  
  1724.     if ( (p = getenv("PVMTMASK")) ) {
  1725.         if ( strlen(p) + 1 == TEV_MASK_LENGTH )
  1726.             BCOPY(p, pvmtrc.tmask, TEV_MASK_LENGTH);
  1727.         else
  1728.             TEV_MASK_INIT(pvmtrc.tmask);
  1729.     } else {
  1730.         TEV_MASK_INIT(pvmtrc.tmask);
  1731.         if ( new_tracer ) need_trcinfo++;
  1732.     }
  1733.  
  1734.     BCOPY(pvmtrc.tmask, pvmctrc.tmask, TEV_MASK_LENGTH);
  1735.  
  1736.     /* get trace buffering from envar */
  1737.  
  1738.     if ((p = getenv("PVMTRCBUF")))
  1739.         pvmtrc.trcbuf = atoi( p );
  1740.     else {
  1741.         pvmtrc.trcbuf = 0;
  1742.         if ( new_tracer ) need_trcinfo++;
  1743.     }
  1744.  
  1745.     pvmctrc.trcbuf = pvmtrc.trcbuf;
  1746.  
  1747.     /* get trace options from envar */
  1748.  
  1749.     if ((p = getenv("PVMTRCOPT")))
  1750.         pvmtrc.trcopt = atoi( p );
  1751.     else {
  1752.         pvmtrc.trcopt = 0;
  1753.         if ( new_tracer ) need_trcinfo++;
  1754.     }
  1755.  
  1756.     pvmctrc.trcopt = pvmtrc.trcopt;
  1757.  
  1758.     /* Setup waitc structures */
  1759.     wait_init(pvmmytid, TIDLOCAL);
  1760.  
  1761.  
  1762.     BZERO(&minfo, sizeof(minfo));
  1763.     minfo.src = -1;
  1764.     minfo.ctx = SYSCTX_TC;
  1765.     minfo.tag = TC_SHMAT;
  1766.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_shmat);
  1767.     minfo.tag = TC_CONREQ;
  1768.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_conreq);
  1769.     minfo.tag = TC_CONACK;
  1770.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_conack);
  1771.     minfo.tag = TC_TASKEXIT;
  1772.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_taskexit);
  1773.     minfo.tag = TC_NOOP;
  1774.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_noop);
  1775.     minfo.tag = TC_SETTRACE;
  1776.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrace);
  1777.     minfo.tag = TC_SETTRCBUF;
  1778.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrcbuf);
  1779.     minfo.tag = TC_SETTRCOPT;
  1780.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settrcopt);
  1781.     minfo.tag = TC_SETTMASK;
  1782.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_settmask);
  1783.     minfo.tag = TC_SIBLINGS;
  1784.     pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvm_tc_siblings);
  1785.  
  1786.     if ( need_trcinfo )
  1787.     {
  1788.         rbf = pvm_setrbuf( 0 );
  1789.  
  1790.         if ( pvm_recvinfo( PVMTRACERCLASS, 0, PvmMboxDefault ) > 0 )
  1791.         {
  1792.             pvm_upkint(&trctid, 1, 1);
  1793.  
  1794.             pvm_upkint(&trcctx, 1, 1);
  1795.             pvm_upkint(&trctag, 1, 1);
  1796.  
  1797.             pvm_upkint(&outctx, 1, 1);  /* unused here */
  1798.             pvm_upkint(&outtag, 1, 1);  /* unused here */
  1799.  
  1800.             pvm_upkstr(tmask);
  1801.  
  1802.             pvm_upkint(&tbuf, 1, 1);
  1803.             pvm_upkint(&topt, 1, 1);
  1804.  
  1805.             if ( pvmtrc.trctid == trctid && pvmtrc.trcctx == trcctx
  1806.                     && pvmtrc.trctag == trctag )
  1807.             {
  1808.                 if ( strlen(tmask) + 1 == TEV_MASK_LENGTH ) {
  1809.                     BCOPY(tmask, pvmtrc.tmask, TEV_MASK_LENGTH);
  1810.                     BCOPY(pvmtrc.tmask, pvmctrc.tmask, TEV_MASK_LENGTH);
  1811.                 }
  1812.  
  1813.                 pvmtrc.trcbuf = tbuf;
  1814.                 pvmctrc.trcbuf = pvmtrc.trcbuf;
  1815.  
  1816.                 pvmtrc.trcopt = topt;
  1817.                 pvmctrc.trcopt = pvmtrc.trcopt;
  1818.             }
  1819.  
  1820.             pvm_freebuf(pvm_setrbuf(rbf));
  1821.         }
  1822.  
  1823.         else
  1824.             pvm_setrbuf(rbf);
  1825.     }
  1826.  
  1827.     tev_init();
  1828.  
  1829.     if (TEV_AMEXCL) {
  1830.         TEV_ENDEXCL;
  1831.     }
  1832.  
  1833.     return cc;
  1834. }
  1835.  
  1836.  
  1837. /* XXX shouldn't clean up unless pvmmytid set?  or at least should check. */
  1838.  
  1839. int
  1840. pvmendtask()
  1841. {
  1842.     int i;
  1843.     struct shmid_ds shmds;
  1844.     struct pmsg *up;
  1845.     int sbf;
  1846.     static struct timeval ztv = { 0, 0 };
  1847.     struct peer *pp;
  1848.     extern struct peer *peers;
  1849.     struct pmsg *mp;
  1850.  
  1851.     /*
  1852.     * free any left-over messages.
  1853.     */
  1854.  
  1855.     pvmsbuf = 0;
  1856.     pvmrbuf = 0;
  1857.     for (i = 1; i < pvmmidhsiz; i++)
  1858.         if (up = pvmmidh[i].m_umb)
  1859.             umbuf_free(up);
  1860.  
  1861.     /*
  1862.     * notify all connected tasks that we are exiting
  1863.     */
  1864.  
  1865.     outta_here = 1;
  1866.  
  1867.     if (peers) {
  1868.         sbf = pvm_initsend(PvmDataFoo);
  1869.         mp = midtobuf(sbf);
  1870.         mp->m_ctx = SYSCTX_TC;
  1871.         pvm_pkint(&pvmmytid, 1, 1);
  1872.  
  1873.         for (pp = peers->p_link; pp != peers; pp = pp->p_link)
  1874.             if (pp->p_tid && pp->p_tid != pvmmytid)
  1875.                 mroute(sbf, pp->p_tid, TC_TASKEXIT, &ztv);
  1876.  
  1877.         pvm_freebuf(sbf);
  1878.     }
  1879.  
  1880.     if (pidtids) {
  1881.         PAGELOCK(&((struct shmpghdr *)infopage)->pg_lock);
  1882.         pidtids[mypidtid].pt_stat = ST_EXIT;
  1883.         PAGEUNLOCK(&((struct shmpghdr *)infopage)->pg_lock);
  1884.     }
  1885.  
  1886.     shmdt(pvminbox);
  1887.     if (shmctl(myshmbufid, IPC_RMID, (struct shmid_ds *)0) == -1)
  1888.         pvmlogperror("pvmendtask() shmctl RMID");
  1889. #ifdef USERECVSEMAPHORE
  1890.     if (semctl(mysemid, 0, IPC_RMID) == -1)
  1891.         pvmlogperror("pvmendtask() semctl RMID");
  1892.     mysemid = -1;
  1893. #endif
  1894.     pvminbox = 0;
  1895.     shmdt(pvmdinbox);
  1896.     pvmdinbox = 0;
  1897.     infopage = 0;
  1898.     pvmdoutbuf = 0;
  1899.     pidtids = 0;
  1900.     mypidtid = -1;
  1901.  
  1902.     peer_cleanup();
  1903.  
  1904.     pvmmytid = -1;
  1905.     if (pvmdsock != -1) {
  1906.         (void)close(pvmdsock);
  1907.         pvmdsock = -1;
  1908.     }
  1909.  
  1910.     /* XXX free rxfrag and rxlist */
  1911. #ifdef LOG
  1912.     fclose(logfp);
  1913. #endif
  1914.  
  1915.     return 0;
  1916. }
  1917.  
  1918.  
  1919. /*    check_for_exit()
  1920. *
  1921. *    If peer struct for task id marked as exited, check for messages
  1922. *    in heap from the task.  If none (borrowing no pages), detach.
  1923. */
  1924.  
  1925. void
  1926. check_for_exit(src)
  1927.     int src;
  1928. {
  1929.     extern struct peer *peers;
  1930.     struct peer *pp;
  1931.  
  1932.     for (pp = peers->p_link; pp != peers; pp = pp->p_link)
  1933.         if (pp->p_tid == src) {
  1934.             if (pp->p_exited) {
  1935.                 int i;
  1936.                 int detach = 1;
  1937.                 struct pmsg *up;
  1938.  
  1939.                 for (i = 1; i < pvmmidhsiz; i++) {
  1940.                     if ((up = pvmmidh[i].m_umb) && (up->m_src == src)) {
  1941.                         detach = 0;
  1942.                         break;
  1943.                     }
  1944.                 }
  1945.  
  1946.                 if (detach) {
  1947.                     peer_detach(pp);
  1948.                 }
  1949.             }
  1950.             break;
  1951.         }
  1952. }
  1953.  
  1954.  
  1955. /************************
  1956.  **  Libpvm Functions  **
  1957.  **                    **
  1958.  ************************/
  1959.  
  1960.  
  1961. int
  1962. pvm_getfds(fds)        /* XXX this function kinda sucks */
  1963.     int **fds;            /* fd list return */
  1964. {
  1965.     int cc;
  1966.  
  1967.     cc = PvmNotImpl;
  1968.     return (cc < 0 ? lpvmerr("pvm_getfds", cc) : cc);
  1969. }
  1970.  
  1971.  
  1972. int
  1973. pvm_start_pvmd(argc, argv, block)
  1974.     int argc;        /* number of args to pass to pvmd (>= 0) */
  1975.     char **argv;    /* args for pvmd or null */
  1976.     int block;        /* if true, don't return until add hosts are started */
  1977. {
  1978.     char *sfn;
  1979.     struct stat sb;
  1980.     int cc;
  1981.     char *fn;            /* file to exec */
  1982.     char **av;
  1983.     int pfd[2];
  1984.     int n;
  1985.     FILE *ff;
  1986.     char buf[128];
  1987.     int x;
  1988.     TEV_DECLS
  1989.  
  1990.     if (TEV_EXCLUSIVE) {
  1991.         if (pvmmytid != -1
  1992.                 && TEV_DO_TRACE(TEV_START_PVMD,TEV_EVENT_ENTRY)) {
  1993.             TEV_PACK_INT( TEV_DID_BF, TEV_DATA_SCALAR, &block, 1, 1 );
  1994.             TEV_PACK_STRING( TEV_DID_AS, TEV_DATA_ARRAY,
  1995.                 argv, argc, 1 );
  1996.             TEV_FIN;
  1997.         }
  1998.     }
  1999.  
  2000.     if (argc < 0 || !argv)
  2001.         argc = 0;
  2002.  
  2003.     if ((pvm_useruid = getuid()) == -1) {
  2004.         pvmlogerror("can't getuid()\n");
  2005.         cc = PvmSysErr;
  2006.         goto bail;
  2007.     }
  2008.  
  2009.     if (!(sfn = pvmdsockfile())) {
  2010.         pvmlogerror("pvm_start_pvmd() pvmdsockfile() failed\n");
  2011.         cc = PvmSysErr;
  2012.         goto bail;
  2013.     }
  2014.  
  2015.     if (stat(sfn, &sb) != -1) {
  2016.         cc = PvmDupHost;
  2017.         goto bail;
  2018.     }
  2019.  
  2020. #ifdef    IMA_TITN
  2021.     if (socketpair(AF_UNIX, SOCK_STREAM, 0, pfd) == -1)
  2022. #else
  2023.     if (pipe(pfd) == -1)
  2024. #endif
  2025.     {
  2026.         cc = PvmSysErr;
  2027.         goto bail;
  2028.     }
  2029.  
  2030.     fn = pvmgetpvmd();
  2031.  
  2032.     av = TALLOC(argc + 2, char *, "argv");
  2033.     if (argc > 0)
  2034.         BCOPY((char *)&argv[0], (char *)&av[1], argc * sizeof(char*));
  2035.     av[0] = fn;
  2036.     av[argc + 1] = 0;
  2037.  
  2038.     if (!fork()) {
  2039.         (void)close(pfd[0]);
  2040.     /* fork again so the pvmd is not the child - won't have to wait() for it */
  2041.         if (!fork()) {
  2042.             if (pfd[1] != 1)
  2043.                 dup2(pfd[1], 1);
  2044.             for (n = getdtablesize(); n-- > 0; )
  2045.                 if (n != 1)
  2046.                     (void)close(n);
  2047.             (void)open("/dev/null", O_RDONLY, 0);    /* should be 0 */
  2048.             (void)open("/dev/null", O_WRONLY, 0);    /* should be 2 */
  2049.             (void)signal(SIGINT, SIG_IGN);
  2050.             (void)signal(SIGQUIT, SIG_IGN);
  2051.             (void)signal(SIGTSTP, SIG_IGN);
  2052.             execvp(av[0], av);
  2053.         }
  2054.         _exit(0);
  2055.     }
  2056.     (void)close(pfd[1]);
  2057.     (void)wait(0);
  2058.     PVM_FREE(av);
  2059.  
  2060.     if (!(ff = fdopen(pfd[0], "r"))) {
  2061.         cc = PvmSysErr;
  2062.         (void)close(pfd[0]);
  2063.         goto bail;
  2064.     }
  2065.  
  2066.     strcpy(buf, "PVMSOCK=");
  2067.     n = strlen(buf);
  2068.     if (!fgets(buf + n, sizeof(buf) - n - 1, ff)) {
  2069.         cc = PvmCantStart;
  2070.         fclose(ff);
  2071.         goto bail;
  2072.     }
  2073.     fclose(ff);
  2074.     if (strlen(buf + n) < 2) {
  2075.         cc = PvmCantStart;
  2076.         goto bail;
  2077.     }
  2078.     n = strlen(buf);
  2079.     if (buf[n - 1] == '\n')
  2080.         buf[n - 1] = 0;
  2081.     pvmputenv(STRALLOC(buf));
  2082. /*
  2083.     fprintf(stderr, "pvm_start_pvmd: %s\n", buf);
  2084. */
  2085.  
  2086.     if (cc = BEATASK)
  2087.         goto bail;
  2088.  
  2089.     if (block) {
  2090.         struct pvmhostinfo *hip;
  2091.         int t = 1;
  2092.  
  2093.         pvm_config((int*)0, (int*)0, &hip);
  2094.         while ((cc = pvm_addhosts(&hip[0].hi_name, 1, (int*)0)) == PvmAlready) {
  2095.             sleep(t);
  2096.             if (t < 8)
  2097.                 t *= 2;
  2098.         }
  2099.         if (cc != PvmDupHost)
  2100.             goto bail;
  2101.         cc = BEATASK;
  2102.     }
  2103.  
  2104. bail:
  2105.  
  2106.     if (TEV_AMEXCL) {
  2107.         if (TEV_DO_TRACE(TEV_START_PVMD,TEV_EVENT_EXIT)) {
  2108.             TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 );
  2109.             TEV_FIN;
  2110.         }
  2111.         TEV_ENDEXCL;
  2112.     }
  2113.  
  2114.     return (cc < 0 ? lpvmerr("pvm_start_pvmd", cc) : 0);
  2115. }
  2116.  
  2117.  
  2118. int
  2119. pvm_precv(tid, tag, cp, len, dt, rtid, rtag, rlen)
  2120.     int tid;
  2121.     int tag;
  2122.     void *cp;
  2123.     int len;
  2124.     int dt;
  2125.     int *rtid;
  2126.     int *rtag;
  2127.     int *rlen;
  2128. {
  2129.     static int last_rbf = 0;
  2130.  
  2131.     int nb, mc, src;
  2132.     int rbf;
  2133.     int cc = 0;
  2134.     long ad;
  2135.     TEV_DECLS
  2136.  
  2137.     if (TEV_EXCLUSIVE) {
  2138.         if (TEV_DO_TRACE(TEV_PRECV,TEV_EVENT_ENTRY)) {
  2139.             TEV_PACK_INT( TEV_DID_RST, TEV_DATA_SCALAR, &tid, 1, 1 );
  2140.             TEV_PACK_INT( TEV_DID_RMC, TEV_DATA_SCALAR, &tag, 1, 1 );
  2141.             ad = (long)cp;
  2142.             TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 );
  2143.             TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &len, 1, 1 );
  2144.             TEV_PACK_INT( TEV_DID_PDT, TEV_DATA_SCALAR, &dt, 1, 1 );
  2145.             TEV_FIN;
  2146.         }
  2147.     }
  2148.  
  2149.     switch (dt) {
  2150.  
  2151.     case PVM_BYTE:
  2152.         len *= sizeof(char);
  2153.         break;
  2154.  
  2155.     case PVM_SHORT:
  2156.     case PVM_USHORT:
  2157.         len *= sizeof(short);
  2158.         break;
  2159.  
  2160.     case PVM_INT:
  2161.     case PVM_UINT:
  2162.         len *= sizeof(int);
  2163.         break;
  2164.  
  2165.     case PVM_LONG:
  2166.     case PVM_ULONG:
  2167.         len *= sizeof(long);
  2168.         break;
  2169.  
  2170.     case PVM_FLOAT:
  2171.         len *= sizeof(float);
  2172.         break;
  2173.  
  2174.     case PVM_CPLX:
  2175.         len *= sizeof(float) * 2;
  2176.         break;
  2177.  
  2178.     case PVM_DOUBLE:
  2179.         len *= sizeof(double);
  2180.         break;
  2181.  
  2182.     case PVM_DCPLX:
  2183.         len *= sizeof(double) * 2;
  2184.         break;
  2185.  
  2186.     case PVM_STR:
  2187.         cc = PvmNotImpl;
  2188.         break;
  2189.  
  2190.     default:
  2191.         cc = PvmBadParam;
  2192.         break;
  2193.     }
  2194.  
  2195.     if (!cc) {
  2196.         if (last_rbf > 0) {
  2197.             pvm_freebuf(last_rbf);
  2198.             last_rbf = 0;
  2199.         }
  2200.         rbf = pvm_setrbuf(0);
  2201.         cc = pvm_recv(tid, tag);
  2202.         if (cc > 0) {
  2203.             pvm_bufinfo(cc, &nb, &mc, &src);
  2204.             if (rlen)
  2205.                 *rlen = nb;
  2206.             if (nb < len)
  2207.                 len = nb;
  2208.             if (rtag)
  2209.                 *rtag = mc;
  2210.             if (rtid)
  2211.                 *rtid = src;
  2212.             pvm_upkbyte((char *)cp, len, 1);
  2213.             last_rbf = cc;
  2214.             cc = 0;
  2215.         }
  2216.         pvm_setrbuf(rbf);
  2217.     }
  2218.  
  2219.     if (TEV_AMEXCL) {
  2220.         if (TEV_DO_TRACE(TEV_PRECV,TEV_EVENT_EXIT)) {
  2221.             TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 );
  2222.             if ( cc < 0 )
  2223.                 nb = mc = src = -1;
  2224.             TEV_PACK_INT( TEV_DID_MNB, TEV_DATA_SCALAR, &nb, 1, 1 );
  2225.             TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &mc, 1, 1 );
  2226.             TEV_PACK_INT( TEV_DID_SRC, TEV_DATA_SCALAR, &src, 1, 1 );
  2227.             TEV_FIN;
  2228.         }
  2229.         TEV_ENDEXCL;
  2230.     }
  2231.  
  2232.     if (cc < 0)
  2233.         lpvmerr("pvm_precv", cc);
  2234.     return cc;
  2235. }
  2236.  
  2237.  
  2238. /* find dynamic buffer */
  2239. char *
  2240. dynbuf(tid, len)
  2241.     int tid;
  2242.     int len;
  2243. {
  2244.     struct peer *pp;
  2245.     int fd;
  2246.     char fname[32];
  2247.     struct shmpghdr *ph;
  2248.  
  2249.     while (!(pp = peer_conn(tid, (int *)0)))
  2250.         ;
  2251. /* XXX this doesn't check for peer_conn returning -1 */
  2252.     if (len > SHMBUFSIZE && len > pp->p_dlen && pp->p_dbuf) {
  2253.         munmap((caddr_t)pp->p_dbuf, SHMBUFSIZE);
  2254.         pp->p_dbuf = 0;
  2255.     }
  2256.  
  2257.     if (!(ph = (struct shmpghdr *)pp->p_dbuf)) {
  2258.         sprintf(fname, PVMSHMFILE, tid);
  2259.         if ((fd = open(fname, O_CREAT|O_RDWR, 0600)) == -1 ||
  2260.         (pp->p_dbuf = (char *)mmap(0, max(len,SHMBUFSIZE), PROT_READ|PROT_WRITE,
  2261. #if defined(IMA_SGIMP) || defined(IMA_SGIMP64)
  2262.         MAP_SHARED|MAP_AUTOGROW, fd, 0)) == (char *)-1L)
  2263. #else
  2264.         MAP_SHARED, fd, 0)) == (char *)-1)
  2265. #endif
  2266.         {
  2267.             pvmlogperror(fname);
  2268.             return (char *)-1L;
  2269.         }
  2270. #ifdef IMA_SUNMP
  2271.         /* fill buffer with 0's */
  2272.         lseek(fd, len - 1, SEEK_SET);
  2273.         write(fd, fname, 1);
  2274. #endif
  2275.         close(fd);
  2276.         pp->p_dlen = len;
  2277.     } else if (ph->pg_ref) {    /* previous msg has not been recv'd */
  2278.         while (ph->pg_ref)
  2279.             if (peer_wait() == -1)
  2280.                 return (char *)-1L;
  2281. #ifdef IMA_SUNMP
  2282.     } else if (pp->p_dlen < len) {
  2283.         if ((fd = open(fname, O_CREAT|O_RDWR, 0600)) == -1) {
  2284.             pvmlogperror(fname);
  2285.             return (char *)-1L;
  2286.         }
  2287.         lseek(fd, len - 1, SEEK_SET);
  2288.         write(fd, fname, 1);
  2289.         close(fd);
  2290.         pp->p_dlen = len;
  2291. #endif
  2292.     }
  2293.  
  2294.     return pp->p_dbuf;
  2295. }
  2296.  
  2297. int
  2298. pvm_psend(tid, tag, cp, len, dt)
  2299.     int tid;
  2300.     int tag;
  2301.     void *cp;
  2302.     int len;
  2303.     int dt;
  2304. {
  2305.     int sbf;
  2306.     int cc = 0;
  2307.     long ad;
  2308.     TEV_DECLS
  2309.  
  2310.     if (TEV_EXCLUSIVE) {
  2311.         if (TEV_DO_TRACE(TEV_PSEND,TEV_EVENT_ENTRY)) {
  2312.             TEV_PACK_INT( TEV_DID_DST, TEV_DATA_SCALAR, &tid, 1, 1 );
  2313.             TEV_PACK_INT( TEV_DID_MC, TEV_DATA_SCALAR, &tag, 1, 1 );
  2314.             ad = (long)cp;
  2315.             TEV_PACK_LONG( TEV_DID_PDA, TEV_DATA_SCALAR, &ad, 1, 1 );
  2316.             TEV_PACK_INT( TEV_DID_PC, TEV_DATA_SCALAR, &len, 1, 1 );
  2317.             TEV_PACK_INT( TEV_DID_PDT, TEV_DATA_SCALAR, &dt, 1, 1 );
  2318.             TEV_FIN;
  2319.         }
  2320.     }
  2321.  
  2322.     switch (dt) {
  2323.  
  2324.     case PVM_BYTE:
  2325.         len *= sizeof(char);
  2326.         break;
  2327.  
  2328.     case PVM_SHORT:
  2329.     case PVM_USHORT:
  2330.         len *= sizeof(short);
  2331.         break;
  2332.  
  2333.     case PVM_INT:
  2334.     case PVM_UINT:
  2335.         len *= sizeof(int);
  2336.         break;
  2337.  
  2338.     case PVM_LONG:
  2339.     case PVM_ULONG:
  2340.         len *= sizeof(long);
  2341.         break;
  2342.  
  2343.     case PVM_FLOAT:
  2344.         len *= sizeof(float);
  2345.         break;
  2346.  
  2347.     case PVM_CPLX:
  2348.         len *= sizeof(float) * 2;
  2349.         break;
  2350.  
  2351.     case PVM_DOUBLE:
  2352.         len *= sizeof(double);
  2353.         break;
  2354.  
  2355.     case PVM_DCPLX:
  2356.         len *= sizeof(double) * 2;
  2357.         break;
  2358.  
  2359.     case PVM_STR:
  2360.         cc = PvmNotImpl;
  2361.         break;
  2362.  
  2363.     default:
  2364.         cc = PvmBadParam;
  2365.         break;
  2366.     }
  2367.  
  2368.     if (!cc) {
  2369. #if 0
  2370.         if ((tid & pvmtidhmask) == (pvmmytid & pvmtidhmask)
  2371.         && (tid & ~pvmtidhmask) != TIDPVMD) {        /* to local task */
  2372.             char *dbuf;
  2373.  
  2374.             len += sizeof(struct shmpghdr);
  2375.             if ((dbuf = dynbuf(tid, len)) != (char *)-1L) {
  2376.                 BCOPY(cp, dbuf, len);
  2377.  
  2378.             } else
  2379.                 cc = PvmSysErr;
  2380.  
  2381.         } else
  2382. #endif /*0*/
  2383.         {
  2384.             sbf = pvm_setsbuf(pvm_mkbuf(PvmDataRaw));
  2385.             pvm_pkbyte((char *)cp, len, 1);
  2386.             if ((cc = pvm_send(tid, tag)) > 0)
  2387.                 cc = 0;
  2388.             pvm_freebuf(pvm_setsbuf(sbf));
  2389.         }
  2390.     }
  2391.  
  2392.     if (TEV_AMEXCL) {
  2393.         if (TEV_DO_TRACE(TEV_PSEND,TEV_EVENT_EXIT)) {
  2394.             TEV_PACK_INT( TEV_DID_CC, TEV_DATA_SCALAR, &cc, 1, 1 );
  2395.             TEV_FIN;
  2396.         }
  2397.         TEV_ENDEXCL;
  2398.     }
  2399.  
  2400.     if (cc < 0)
  2401.         lpvmerr("pvm_psend", cc);
  2402.     return cc;
  2403. }
  2404.  
  2405.  
  2406. /* XXX copied from lpvm.c as needed by pvmmcast */
  2407. /* XXX duplicate code should be cleaned up in a support lpvm* file [GEF97] */
  2408.  
  2409. static int
  2410. int_compare(i, j)
  2411. #if defined(IMA_SGI) || defined(IMA_SGI5) || defined(IMA_SGI64) || defined(IMA_SGIMP) || defined(IMA_SGIMP64)
  2412.     const void *i, *j;
  2413. #else
  2414.     void *i, *j;
  2415. #endif
  2416. {
  2417.     return *((int *)i) - *((int *)j);
  2418. }
  2419.  
  2420.  
  2421. /* XXX copied from lpvm.c as needed by pvmmcast again */
  2422. /* XXX duplicate code should be cleaned up in a support lpvm* file [GEF97] */
  2423. /* XXX, XXX!! note that although shmem is a MPP port I had to take out the */
  2424. /* XXX ISA_MPP section as MPP_TTPCB_FIND won't work for shmem machines yet! */
  2425.  
  2426. /*  ttpcb_find()
  2427. *
  2428. *   Find a task-task entry by tid in ttlist.
  2429. */
  2430.  
  2431. struct ttpcb *
  2432. ttpcb_find(tid)
  2433.     int tid;        /* peer tid */
  2434. {
  2435.     struct ttpcb *pcbp;
  2436.  
  2437. /* GEF fire fighter (TM) */
  2438. /*     return (struct ttpcb*)0; */
  2439.  
  2440. #if defined(IMA_MPP)
  2441.     if ( pcbp = mpp_ttpcb_find(tid))
  2442.         return pcbp;
  2443. #endif
  2444.     for (pcbp = ttlist->tt_link; pcbp != ttlist; pcbp = pcbp->tt_link)
  2445.         if (pcbp->tt_tid >= tid)
  2446.             break;
  2447.     return (pcbp->tt_tid == tid) ? pcbp : (struct ttpcb*)0;
  2448. }
  2449.  
  2450.  
  2451.  
  2452. /* XXX copied from lpvm.c as needed by lpvmgen.c */
  2453.  
  2454. /*  pvmmcast()
  2455. *
  2456. *   Multicast a message to a list of destinations.
  2457. */
  2458.  
  2459. int
  2460. pvmmcast(mid, tids, count, tag)
  2461.     int mid;
  2462.     int *tids;
  2463.     int count;
  2464.     int tag;
  2465. {
  2466.     static struct timeval ztv = { 0, 0 };
  2467.  
  2468.     int *dst;
  2469.     int i, j;
  2470.     int cc = 0;
  2471.     struct ttpcb *pcbp;
  2472.     int sbf;
  2473.     struct pmsg *mp;
  2474.  
  2475.     /*
  2476.     * make sorted list of destinations
  2477.     */
  2478.     dst = TALLOC(count, int, "mcal");
  2479.     BCOPY(tids, dst, count * sizeof(int));
  2480.     qsort((char*)dst, count, sizeof(int), int_compare);
  2481.  
  2482.     /*     pvmsbuf->m_ctx = pvmmyctx; */
  2483.     /* we are sending mesg mid which may not the same as pvmsbuf->m_mid */
  2484.     mp = midtobuf(mid);
  2485.     mp->m_ctx = pvmmyctx;
  2486.  
  2487.     /*
  2488.     * remove duplicates
  2489.     */
  2490.     j = 0;
  2491.     for (i = 1; i < count; i++)
  2492.         if (dst[i] != dst[j])
  2493.             dst[++j] = dst[i];
  2494.     count = j + 1;
  2495.  
  2496.     /*
  2497.     * remove self from list
  2498.     * send over any direct routes we have
  2499.     *
  2500.     * XXX we should attempt new routes here if RouteDirect is on.
  2501.     */
  2502.     j = 0;
  2503.     for (i = 0; i < count; i++) {
  2504.         if (dst[i] == pvmmytid)
  2505.             continue;
  2506.         /* if ((pcbp = ttpcb_find(dst[i])) && pcbp->tt_state == TTOPEN) */
  2507.             /* mroute(pvmsbuf->m_mid, dst[i], tag, &ztv); */
  2508.         /* else */
  2509.             dst[j++] = dst[i];
  2510.     }
  2511.     count = j;      /* destinations still to go */
  2512.  
  2513.     /*
  2514.     * send rest of addresses to pvmd for distribution
  2515.     */
  2516.     if (count > 0) {
  2517.         /* announce multicast address list to pvmd */
  2518.         sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  2519.         pvm_pkint(&count, 1, 1);
  2520.         pvm_pkint(dst, count, 1);
  2521.         sbf = pvm_setsbuf(sbf);
  2522.         if ((cc = mroute(sbf, TIDPVMD, TM_MCA, &ztv)) > 0)
  2523.             cc = 0;
  2524.         pvm_freebuf(sbf);
  2525.  
  2526.         /* send message */
  2527.         if (cc >= 0)
  2528. /*             if ((cc = mroute(pvmsbuf->m_mid, pvmmytid | TIDGID, tag, &ztv)) > 0) */
  2529.             if ((cc = mroute(mid, pvmmytid | TIDGID, tag, &ztv)) > 0)
  2530.                 cc = 0;
  2531.     }
  2532.  
  2533.     PVM_FREE(dst);
  2534.     return cc;
  2535. }
  2536.  
  2537.  
  2538. /* XXX copied from lpvm.c as needed by lpvmgen.c */
  2539. int
  2540. post_routedelete(tid, ctx, tag)
  2541.     int tid;
  2542.     int ctx;
  2543.     int tag;
  2544. {
  2545.     int sbf;
  2546.     struct waitc *wp;
  2547.     struct pmsg *up;
  2548.     int i;
  2549.  
  2550.     sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  2551.     pvm_pkint(&tid, 1, 1);
  2552.     i = -1;
  2553.     pvm_pkint(&i, 1, 1);
  2554.     sbf = pvm_setsbuf(sbf);
  2555.     up = midtobuf(sbf);
  2556.     up->m_ctx = ctx;
  2557.     up->m_tag = tag;
  2558.  
  2559.     if (ttpcb_find(tid)) {
  2560.         wp = wait_new(WT_ROUTED);
  2561.         wp->wa_tid = pvmmytid;
  2562.         wp->wa_on = tid;
  2563.         wp->wa_mesg = up;
  2564.  
  2565.     } else {
  2566.         mesg_input(up);
  2567.     }
  2568.     return 0;
  2569. }
  2570.  
  2571.  
  2572.  
  2573. /*    shmemuptod()
  2574.  *
  2575.  *    Move message frags between task and pvmd using SOCKETs only.
  2576.  *    Returns when
  2577.  *        Outgoing message fully sent or
  2578.  *        (Timed out (tmout) OR errored.
  2579.  *
  2580.  *    Returns 0 if OK, or negative on error.
  2581.  */
  2582.  
  2583. #define HEADER_SIZE (TDFRAGHDR + MSGHDRLEN)
  2584.  
  2585. static int
  2586. shmemuptod(txup)
  2587.     struct pmsg *txup;            /* outgoing message */
  2588. {
  2589.     struct frag *txfp = 0;        /* cur ogm frag or null */
  2590.     struct timeval tin;
  2591.     struct timeval tnow;
  2592.     struct timeval *tvp;
  2593.     fd_set rfds, wfds;
  2594.     int ff;
  2595.     int n;
  2596. #ifdef SOCKLENISUINT
  2597.     size_t oslen;
  2598. #else
  2599.     int oslen;
  2600. #endif
  2601.     char *txcp = 0;                /* point to remainder of txfp */
  2602.     int txtogo = 0;                /* len of remainder of txfp */
  2603.     struct sockaddr_in sad;
  2604.     int s;
  2605.     struct msgid *sendmsg = (struct msgid *) NULL;
  2606.     char errtxt[64];
  2607.     int upfd;                    /* one-way socket to the daemon */
  2608.  
  2609.     if (txup) {
  2610.     /* transmitting a umsg */
  2611.         txfp = txup->m_frag->fr_link;
  2612.         if (!txfp->fr_buf) {
  2613.             if (!(txfp = fr_new(MAXHDR)))
  2614.                 return PvmNoMem;
  2615.             txfp->fr_dat += MAXHDR;
  2616.             LISTPUTBEFORE(txup->m_frag, txfp, fr_link, fr_rlink);
  2617.         }
  2618.  
  2619.         /* To the daemon ? */
  2620.         upfd = pvmdsock;
  2621.  
  2622.         /* txup->m_ref++; */
  2623.     }
  2624.  
  2625.     if (pvmdebmask & PDMMESSAGE) {
  2626.         pvmlogprintf("shmemuptod() mid %d", (txup ? txup->m_mid : 0));
  2627.         if (txup) {
  2628.             pvmlogprintf(" ctx %d tag %s",
  2629.                     txup->m_ctx,
  2630.                     pvmnametag(txup->m_tag, (int *)0));
  2631.         }
  2632.     }
  2633.  
  2634.     /* must block sending to pvmd */
  2635.     tvp = (struct timeval *) NULL;
  2636.  
  2637.     /* We haven't sent anything, yet, Build Header */
  2638.  
  2639.     txcp = txfp->fr_dat; /* packed data */
  2640.     /* XXXX we assume thats its only packed data TMs */
  2641.  
  2642.     txtogo = txfp->fr_len;    /* actual data size */
  2643.  
  2644.     /*
  2645.      * This is first and last frag. So prepend message header
  2646.      */
  2647.     txcp -= MSGHDRLEN;
  2648.     txtogo += MSGHDRLEN;
  2649.     pvmput32(txcp,
  2650.             (txup->m_enc == 0x20000000 ? pvmmydsig : txup->m_enc));
  2651.     pvmput32(txcp + 4, txup->m_tag);
  2652.     pvmput32(txcp + 8, txup->m_ctx);
  2653.     pvmput32(txcp + 16, txup->m_wid);
  2654. #ifdef    MCHECKSUM
  2655.     pvmput32(txcp + 20, umbuf_crc(txup));
  2656. #else
  2657.     pvmput32(txcp + 20, 0);
  2658. #endif
  2659.     ff = FFSOM | FFEOM;    /* Alpha Omega: first and last frag man */
  2660.  
  2661.     /*
  2662.      * prepend frag header
  2663.      */
  2664.     txcp -= TDFRAGHDR;
  2665.     pvmput32(txcp, txup->m_dst);
  2666.     pvmput32(txcp + 4, pvmmytid);
  2667.     pvmput32(txcp + 8, txtogo);
  2668.     pvmput32(txcp + 12, 0);        /* to keep putrify happy */
  2669.     pvmput8(txcp + 12, ff);
  2670.     txtogo += TDFRAGHDR;
  2671.  
  2672.     /*
  2673.      * Make sure we have a valid socket address 
  2674.      * Prod will connect us to the daemon if we are not already
  2675.      * connected.
  2676.      */
  2677.  
  2678.     if ( pvmdsock < 0 ) {
  2679.  
  2680.         prodpvmd();            /* connect to the daemon setting pvmdsock */
  2681.  
  2682.         if ( pvmdsock < 0 ) {    /* nested yuck.. */
  2683.             pvmlogerror("shmemuptod() Can't get daemon socket open\n");
  2684.             pmsg_unref(txup);   /* unref the message */
  2685.             return -1;
  2686.         }
  2687.     }
  2688.  
  2689.     if (pvmdebmask & PDMPACKET) {
  2690.         pvmlogprintf("shmemuptod() dst t%x n=%d\n",
  2691.                 txup->m_dst, txtogo);
  2692.     }
  2693.  
  2694.     /* XXX yep... blocking loop forever!!!!! */
  2695.     /* If I can't get 100+ bytes up that socket we are */
  2696.     /* in trouble anyway! */
  2697.     while (txtogo) {
  2698.  
  2699. #if defined(IMA_RS6K) || defined(IMA_SP2MPI) || defined(IMA_AIX4) || defined (IMA_AIX4MP)
  2700.         n = write(pvmdsock, txcp, min(txtogo, 4096));
  2701. #else
  2702.         n = write(pvmdsock, txcp, txtogo);
  2703. #endif
  2704.  
  2705.         if (pvmdebmask & PDMPACKET)
  2706.             pvmlogprintf("shmemuptod() wrote %d\n", n);
  2707.  
  2708.         if (n == -1 && errno != EWOULDBLOCK && errno != EINTR)
  2709.         {
  2710.             pvmlogperror("shmemuptod() write pvmd sock");
  2711.             return PvmSysErr;
  2712.         }
  2713.  
  2714.         if (n > 0)
  2715.         {
  2716.             txcp += n;
  2717.             txtogo -= n;
  2718.         }
  2719.  
  2720.     } /* while we have data to send */
  2721.  
  2722.  
  2723.     /* we made it here so the message went! */
  2724.  
  2725.     pmsg_unref(txup);    /* unref the message */
  2726.  
  2727.     return 0;
  2728. }
  2729.  
  2730.  
  2731. int
  2732. send_my_pid()
  2733. {
  2734.     struct pmsg *up;
  2735.     int sbf;
  2736.     int cc;
  2737.  
  2738.     sbf = pvm_setsbuf(pvm_mkbuf(PvmDataFoo));
  2739.     pvm_pkint(&pvmmyupid, 1, 1);
  2740.     sbf = pvm_setsbuf(sbf);
  2741.  
  2742.     up = midtobuf(sbf);
  2743.     up->m_dst = TIDPVMD;
  2744.     up->m_tag = TM_SHMCONN;
  2745.     up->m_ctx = SYSCTX_TM;
  2746.  
  2747.     /* I would love a mxfer... but we have to use a custom */
  2748.     /* one-off routine! */
  2749.     /* cc = mxfer(up2, &ztv); */
  2750.     cc = shmemuptod (up);
  2751.  
  2752.     pvm_freebuf(sbf);
  2753.     return cc;
  2754. }
  2755.  
  2756.  
  2757. int
  2758. sleep_dammit( msecs )
  2759. int msecs;
  2760. {
  2761. #if defined(IMA_SUNMP) || defined(IMA_RS6KMP) || defined(IMA_AIX4MP)
  2762.     return( usleep( msecs ) );
  2763. #else
  2764.     struct timeval biteme;
  2765.  
  2766.     biteme.tv_sec = 0;
  2767.     biteme.tv_usec = msecs;
  2768.  
  2769.     while ( biteme.tv_usec > 1000000 )
  2770.     {
  2771.         (biteme.tv_sec)++;
  2772.         biteme.tv_usec -= 1000000;
  2773.     }
  2774.  
  2775.     return( select( 0,
  2776. #ifdef    FDSETISINT
  2777.                 (int *) NULL, (int *) NULL, (int *) NULL,
  2778. #else
  2779.                 (fd_set *) NULL, (fd_set *) NULL, (fd_set *) NULL,
  2780. #endif
  2781.                 &biteme ) );
  2782. #endif
  2783. }
  2784.  
  2785.